Promise.all() 不等待异步进程

Wil*_*ger 6 asynchronous node.js promise es6-promise

在 Node.js 中,我尝试循环某些项目,为每个项目完成一个异步过程,然后等待每个项目完成后再开始下一个项目。我一定做错了什么,因为 Promise.all() 没有等待任何异步进程完成!我的代码如下:

getChildLessons() {

 return new Promise((resolve, reject) => {

  Promise.all(

    //nested for loop is needed to get all information in object / arrays
   this.lessons.levels.map((item, i) => {

      item.childlevels.map((childItem, iChild) => {

        return ((i, iChild) => {

          //return async process with Promise.resolve();
          return this.horseman
          .open(childItem.url)
          .html()
          .then((html) => {
            //adding some information to an array
          })
          .then(() => {
              return Promise.resolve();
          }).catch((err) => {
            reject(err);
          });

        })(i, iChild);

      });
  })

  // Promise.all().then()
).then(() => {
  resolve(this.lesson);
})
.catch((err) => {
  console.log(err);
});
});
}
Run Code Online (Sandbox Code Playgroud)

我对 Node.js 异步还很陌生,所以如果可能的话,请您提供一个清晰的示例。

tri*_*cot 6

需要解决两个问题才能使其正常工作:

  • 提供给外部调用的回调map没有return语句,因此会map创建一个数组,其中所有元素都是undefined。您需要return的结果child.items.map,即一系列承诺。
  • 一旦修复了上述问题,外部map将返回一个数组的数组。这个 2D 承诺数组需要扁平化为一个简单的承诺数组。您可以使用[].concat和 扩展语法来做到这一点。

所以你的代码的第一行应该变成:

Promise.all(
    [].concat(...this.lessons.levels.map((item, i) => {
        return item.childlevels.map((childItem, iChild) => {
Run Code Online (Sandbox Code Playgroud)

concat(在适当的位置添加一个右括号——以结束参数列表——。

其他一些备注:

根据定义,所调用的 Promise.then在调用回调时已解决。在那一刻返回已解决的承诺并不会增加任何有用的东西。返回被调用的承诺.then就可以了。.then您只需从链中删除上述调用即可。

  • 快结束时你打电话resolve(this.lesson)这是Promise 构造函数反模式的示例。你不应该创建一个新的 Promise,而是返回调用的结果Promise.all,并在其.then调用内部返回 this.lesson,以便它成为承诺的值。

将所有的承诺串联起来

要链接所有承诺而不是使用Promise.all,如果使用async/await语法是最简单的。像这样的东西:

async getChildLessons() {
    for (let item of this.lessons.levels) {
        for (let childItem of item.childlevels) {
            let html = await this.horseman
                                 .open(childItem.url)
                                 .html();
            //adding some information to an array
            // ...
        }
    }
    return this.lesson;
}
Run Code Online (Sandbox Code Playgroud)


Lon*_*han 0

也许尝试做这样的事情?

let firstPromise = new Promise((resolve,reject) => {
    // your logic/code
})

//add more promises you want into array if u want


 Promise.all([firstPromise])
.then((response) => {
    //do stuff with response
})
.catch((error) => {
    //do stuff with error
})
Run Code Online (Sandbox Code Playgroud)