简体   繁体   中英

wait for foreach to finish before executing next lines

I want the code to wait for the foreach function to complete before going to the next line to perform the if statement on the counter number. I am sure I have to put a Promise somewhere... but I also thought that .then() would do the trick?

It appears there are examples of this but I am not able to figure this one out or where Im going wrong here:

      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,
              });
            });
        
          };

Appreciate any help I can get. Thanks!

First off, when you're using async , the await keyword essentially replaces .then . In other words:

ref
        .collection(‘foo’)
        .where(‘open’, '==', true)
        .get()
        .then(async snapshot => {
        // indented code that uses snapshot

can become:

const snapshot = await ref
        .collection(‘foo’)
        .where(‘open’, '==', true)
        .get();
// not-indented code that uses snapshot

When you use await in this way the browser will pause your code and "restart it" when the request returns, the exact same way as with .then (because it's literally just syntactic sugar on top of promises).

Second, as @Doug Stevenson noted in a comment, forEach doesn't pause on promises, so when doing asynchronous work what you really want to do is use map instead of a forEach , and combine it with Promise.all , like so:

await Promise.all(someArray.map(async x => ...))

In other words, you want your (formerly) forEach callback to return a promise, and map lets you do that (vs. forEach returns nothing). Promise.all will convert each of those individual promises into one big one, which you can then await or chain a .then off.

When that big promise resolves (either with .then or await ) it will have an array as a resolved value, and that array will contain all of the resolved values from the original promises. In other words if you do:

const foo = await Promise.all(arrayOfPromises);

then foo will be an array containing what would have been passed as the .then / await value for each of the promises in the passed-in arrayOfPromises .

javascript code, by default will finish before moving on to the next line. That's its natural behavior. It you just write code normally it will execute one line at a time.

you have added a "async" tag to you code and then asked for it to not run in an async way, which is note entirely logical.

if you want your code to execute in a way that it finishes the foreach, simply don't add any async tags.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM