首页 > 解决方案 > 如何使用异步代码以正确的顺序记录响应

问题描述

我需要创建一个对数组中的每个项目运行“getFile”函数的函数。getFile 函数记录“x 的文件内容”x 是数组中的任何元素。

目前,我有一个工作函数,它在数组上运行 getFile 并在记录结果之前等待最终响应。

但是,我现在需要在收到响应时按顺序记录它们。例如,如果我的数组当前是 [1, 2, 3, 4, 5],它会以随机顺序记录“x 的文件内容”,因此如果要返回日志,则 3 然后 4 然后 1。我收到 1,我需要记录它,然后一旦我收到 2 个日志,依此类推。

我将在下面插入我当前的代码。我遇到的问题是我需要知道我的阵列中的“空白空间”何时被填充,以便我可以实时记录它。因此,允许我的用户查看结果,而不必等到所有响应都返回

function fetchContentOfFiles(fileNames, testCB) {
  const fileContent = [];
  let counter = 0;

  fileNames.forEach((file, i) => {
    getFile(file, (err, fileName) => {
      if (err) console.log(err)
      else {
        fileContent[i] = fileName;
        counter++
        if (counter === fileNames.length) {
          testCB(null, fileContent)
        };
        console.log(fileContent)
      };
    });
  });
};

标签: javascriptfunctionasynchronous

解决方案


最简洁的编写方法是在函数中使用for循环。asyncPromisifygetFile使其返回 a Promise,然后在循环的每次迭代中等待它。在循环结束时,调用回调:

const getFileProm = file => new Promise((resolve, reject) => {
  getFile(file, (err, fileName) => {
    if (err) reject(err);
    else resolve(fileName);
  });
});

async function fetchContentOfFiles(fileNames, testCB) {
  const fileContent = [];
  try {
    for (let i = 0; i < fileNames.length; i++) {
      fileContent.push(
        await getFileProm(fileNames[i])
      );
    }
  } catch(e) {
    // handle errors, if you want, maybe call testCB with an error and return?
  }
  testCB(null, fileContent);
}

如果作为 PromisefetchContentOfFiles调用和处理而不是使用回调可能会更好,然后可以在消费者中处理错误:

async function fetchContentOfFiles(fileNames) {
  const fileContent = [];
  for (let i = 0; i < fileNames.length; i++) {
    fileContent.push(
      await getFileProm(fileNames[i])
    );
  }
  return fileContent;
}

fetchContentOfFiles(arr)
  .then((fileContent) => {
    // do stuff with fileContent
  })
  .catch((err) => {
    // something went wrong
  });

推荐阅读