我希望代码先等待foreach函数完成,然后再转到下一行对计数器编号执行if语句。我确定我必须在某个地方放一个Promise ...,但是我还认为.then()可以解决问题?
似乎有这样的例子,但我无法弄清楚这一点或我在哪里出错了:
async getSomeData () {
const data = [];
const ref = fire.firestore();
ref
.collection(‘foo’)
.where(‘open’, '==', true)
.get()
.then(async snapshot => {
let count = 0;
snapshot
.docs
.forEach(async doc => {
const {foo, bar} = doc.data();
const number_count = await this.getNumber(doc.id);
if (number_count >= 1){
count++;
data.push({
foo,
bar
});
this.setState({
data : data,
});
}
})
.then() ?????
**//THIS IS EXECUTING BEFORE THE FOREACH FINISHES**
if(count==0){
this.setState({
isLoading: false,
noStores: true
});
}
}).catch(error => {
console.log(error);
//if fails
this.setState({
noStores : true,
});
});
};
感谢我可以获得的任何帮助。谢谢!
答案 0 :(得分:0)
首先,当您使用async
时,await
关键字实际上替代了.then
。换句话说:
ref
.collection(‘foo’)
.where(‘open’, '==', true)
.get()
.then(async snapshot => {
// indented code that uses snapshot
可以成为:
const snapshot = await ref
.collection(‘foo’)
.where(‘open’, '==', true)
.get();
// not-indented code that uses snapshot
当您以这种方式使用await
时,浏览器 将暂停您的代码,并在请求返回时“重新启动”,这与完全相同 .then
(因为从字面上看,它只是诺言之上的语法糖)。
第二,正如@Doug Stevenson在评论中指出的那样,forEach
不会在promise上暂停,因此在进行异步工作时,您真正想做的是使用map
而不是{{1 }},并将其与forEach
组合,如下所示:
Promise.all
换句话说,您希望(以前)await Promise.all(someArray.map(async x => ...))
回调函数返回承诺,而forEach
则允许您这样做(与map
不返回任何内容)。 forEach
会将每个单独的承诺转换成一个大的承诺,然后您可以Promise.all
或将await
链接起来。
当大承诺解决时(使用.then
或.then
),它将有一个数组作为已解决的值,并且该数组将包含原始承诺的所有已解决的值。换句话说,如果您这样做:
await
然后const foo = await Promise.all(arrayOfPromises);
将是一个数组,其中包含将传递的 作为foo
/ .then
值传递给传入的每个promise的值await
。
答案 1 :(得分:0)
javascript代码,默认情况下将在继续进行下一行之前完成。那是它的自然行为。只要您通常编写代码,它将一次执行一行。
您已经在代码中添加了“异步”标签,然后要求它不以异步方式运行,这完全符合逻辑。
如果您希望代码以完成foreach的方式执行,只需不添加任何异步标记即可。