如何修改传递给 Promise.all 的数组

How can I modify the array passed to Promise.all

我的 node.js class 正在从文件系统异步递归加载文件。

我的 class 的其他方法在所有文件加载完成后才有效,所以我定义了一个承诺数组,并在执行依赖于的方法之前对该数组执行 Promise.all()正在加载完成。

当代码发现每个文件或目录时,它会向数组添加一个新的承诺,以便数组最终包含一个针对扫描的每个目录和加载的每个文件的承诺。我已经验证这是按设计工作的。

问题是 Promise.all() 似乎只等待调用时数组中已经存在的承诺,而不等待 Promise.all() 之后添加到数组中的承诺调用,因此 Promise.all() 返回的承诺在所有文件加载之前就已解决。

是的,我确实确保在解决当前承诺之前将新承诺添加到数组中以避免出现竞争情况。

假设我不能在这种情况下使用 Promise.all(),最好的选择是什么?

我认为你应该先遍历文件系统的树以获取所有文件的路径并将它们存储在一个数组中,然后Promise.all那个数组。

像这样:

(我正在使用 lodash)

async function getPaths(dir) {
  const files = [];
  const promises = [];
  const contents = await fs.readdir(dir);

  for (const content of contents) {
    if(_.endsWith(content, '.js')) { // only get JS files
      files.push(path.resolve(dir, content));
    }
    else {
      promises.push(getPaths(path.resolve(dir, content)));
    }

  }
  let subDirFiles = await Promise.all(promises);
  subDirFiles = _.flatten(subDirFiles);

  return _.union(files, subDirFiles); // contain all files paths from a root `dir`
}

感谢 link 到 。使用来自该线程的信息,我能够提出一个可行的解决方案,如下所示:

  private readonly loadingPromises: Promise<any>[];

  private async finishLoading(): Promise<void> {
    var completedCount = 0;
    while (this.loadingPromises.length != completedCount) {
      var waitCount = this.loadingPromises.length;
      await Promise.all(this.loadingPromises);
      completedCount = waitCount;
    }
    this.loadingPromises.length = 0;
  }

  async somePublicMethod() {
    return this.finishLoading().then(() => {
      //... do stuff here
    });
  }