等待foreach完成之后再执行下一行

时间:2020-08-28 22:08:51

标签: javascript firebase

我希望代码先等待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,
              });
            });
        
          };

感谢我可以获得的任何帮助。谢谢!

2 个答案:

答案 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的方式执行,只需不添加任何异步标记即可。