在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);
});
});
}
我对与node.js的异步相当新,所以如果可能的话,请你提供一个明确的例子。
答案 0 :(得分:1)
需要修复的两个问题才能使其发挥作用:
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) => {
在适当的位置添加一个右括号 - 关闭concat(
的参数列表。
其他一些评论:
以下代码无用:
.then(() => {
return Promise.resolve();
})
根据定义调用.then
的承诺在调用回调时解决。要在此刻返回已解决的承诺,不会添加任何有用的内容。要返回调用.then
的承诺就好了。您只需从链中删除上述.then
来电即可。
在结束时,您拨打resolve(this.lesson)
。这是promise constructor anti pattern的一个例子。您不应该创建新的Promise,而是返回Promise.all
调用的结果,并在其.then
调用返回 this.lesson
内,以便它成为承诺值。
要链接所有承诺而不是使用Promise.all
,最简单的方法是使用async/await
语法。像这样:
async getChildLessons() {
this.lessons.levels.forEach((item, i) => {
item.childlevels.map((childItem, iChild) => {
((i, iChild) => {
let html = await this.horseman
.open(childItem.url)
.html();
.catch((err) => {
throw(err); // throw instead of reject
});
//adding some information to an array
})(i, iChild);
});
})
return this.lesson;
}
答案 1 :(得分: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
})
答案 2 :(得分:0)
以下代码行无法返回任何内容。您正在尝试将未定义的数组传递给Promise.all
this.lessons.levels.map((item, i) => {...})
但是,您的代码还有其他几个问题。下面的块完全没必要。除了在代码中添加额外的块之外,它几乎什么都不做。
return ((i, iChild) => {...})(i, iChild);
您无需从主函数返回Promise
。 Promise.all()
的结果是Promise
。
考虑到上述情况,这是一段代码片段。
// an array of Promises
var levelPromises = this.lessons.levels.map((item, i) => {
var childPromises = item.childlevels.map((childItem, iChild) => {
return this.horseman.open(childItem.url)
//...
})
return Promise.all(childPromises)
})
return Promise.all(levelPromises)