异步文件读取,无法使函数在返回前完成

Asynchronous file reading, cannot make function finish before returning

我正在尝试读取文件夹中的所有文件,检查它是否有 featured: true 道具,如果有则增加计数器,如果有超过 1 个这样的文件则抛出错误。但出于某种原因,我的代码没有等待,直接跳转到最后一部分,这是输出

this should be last
Inside item, looking for featured prop
Inside item, looking for featured prop

我的代码:

const fs = require('fs');
const findInDir = require('./utils/findInDir');

(async () => {
  const dir = './public/page-data/blog';
  const fileRegex = /.*/;
  const allFiles = findInDir(dir, fileRegex);
  let result = 0;

  await allFiles.map(file => {
    fs.readFile(file, 'utf8', (err, data) => {
      const obj = JSON.parse(data);

      if (obj.result.pageContext.featured === true) {
        console.log('Inside item, looking for featured prop');
        result += 1;
      }
    });
  });

  console.log('this should be last');

  if (result > 1) {
    throw new Error('There are multiple featured blog posts, please fix.');
  }
})();

需要一些帮助来理解我做错了什么。

您需要使用 fs.readFile 的非回调版本才能真正 await 读取文件。使用 .map 也没有多大意义,因为您实际上并没有映射某些东西,所以只需使用 for .. of 循环:

for (const file of allFiles){
 try {
   const data = await fs.promises.readFile(file);
   // ...
 } catch(err) {
   // handle error
 }
}

console.log('this should be last');

快速解决方案:

(async () => {
  const dir = "./public/page-data/blog";
  const fileRegex = /.*/;
  const allFiles = findInDir(dir, fileRegex);

  try {
    await Promise.all(
      allFiles.map((file) => {
        return new Promise((resolve, reject) => {
          fs.readFile(file, "utf8", (err, data) => {
            const obj = JSON.parse(data);

            if (obj.result.pageContext.featured === true) {
              reject("Inside item, looking for featured prop");
            } else {
              resolve();
            }
          });
        });
      })
    );
  } catch (err) {
    throw new Error("There are multiple featured blog posts, please fix.");
  }
})();

我不是像在循环中那样逐一检查每一项,而是这样做的。如果其中任何一个 featured 设置为真,它会检查“平行”。因此它比循环更快

如果它 true 我拒绝它并且 Promise.all() 停止。 Promise.all()try / catch 捕获拒绝


您只需要了解一件事就可以知道何时使用 await 何时不使用。

只有在承诺上使用 await 才有意义。

你怎么知道它是否是一个承诺?就console.log

它是否控制台日志 Promise?使用 await

它不是控制台日志 Promise 吗?使用 await

没有意义

这 return 只是一个数组。使用 await 有意义吗?不,它不 return Promise

但是如果你这样做:

你有一系列的承诺。 这里有点不同。你有一个数组,但里面的元素是一个承诺。 您可以使用 Promise.all() 它基本上等待数组中的每个项目直到完成。