如何使用异步代码以正确的顺序记录响应

时间:2019-01-15 10:00:52

标签: javascript function asynchronous

我需要创建一个在数组中的每个项目上运行'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)
      };
    });
  });
};

1 个答案:

答案 0 :(得分:1)

最干净的方法是在for函数内使用async循环。承诺getFile,以便它返回一个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);
}

如果fetchContentOfFiles被作为Promise 调用并处理为 而不是使用回调,则可能会更好,然后可以在使用者中处理错误:

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
  });