0

Using await in a for loop within an async function provides the expected result of the execution awaiting the completion of the current Promise within the iteration

const story = [1,2,3,4,5];

(async() => {

  for (var i = 0; i < story.length; i++) {
    await new Promise(function(resolve) {
      setTimeout(function() {
        resolve(story[i])
      }, 1000)
    }).then(function(chapter) {
      document.body
        .appendChild(document.createTextNode(chapter));
    });
  }

})()

Why does Array.prototype.forEach() not provide the same functionality of awaiting the fulfillment of the current Promise when await is using within the callback passed to .forEach()?

const story = [1,2,3,4,5];

(async() => {

  story.forEach(async function(chapterUrl) {
    // does not await for Promise fulfillment
    await new Promise(function(resolve) {
      setTimeout(function() {
        resolve(chapterUrl)
      }, 1000)
    }).then(function(chapter) {
      document.body
      .appendChild(document.createTextNode(chapter));
    });
  });
  
})();
guest271314
  • 1
  • 15
  • 104
  • 177
  • @KevinB Unfortunately none of the answers explain _why_ – guest271314 Jan 19 '18 at 21:26
  • 1
    The comments however do. Feel free to add a better answer there if you have one – Kevin B Jan 19 '18 at 21:27
  • 1
    @KevinB No, they do not. Unless you can link to the specific comments. If were to state the same thing would summarily be advised to put answers in answers instead of comments. – guest271314 Jan 19 '18 at 21:34
  • 3
    The answer itself does get into why forEach doesn't work. *"If you want to read the files in parallel, you cannot use forEach indeed. Each of the the async callback function calls does return a promise, **but you're throwing them away instead of awaiting them**."* of course, because forEach doesn't do anything with what the functions passed to it returns. it just doesn't quite spell it out as much as you might want it to. – Kevin B Jan 19 '18 at 21:37
  • 1
    It then continues with a .map solution that *does* work, for that very reason. – Kevin B Jan 19 '18 at 21:38
  • @KevinB You are referring to a comment, correct? And not a formal answer to the present Question? You cannot massage an answer to the present Question from comments following answers which did not answer the present question – guest271314 Jan 19 '18 at 21:40
  • No, i'm referring to the accepted answer. – Kevin B Jan 19 '18 at 21:40
  • The accepted answer does not explain _why_ there is different effect using `.forEach()` as to `for..in`, `for..of` or `for`. `for` loops do not `return` anything either – guest271314 Jan 19 '18 at 21:41
  • 3
    Yes it does. It explains that forEach cannot handle async callbacks properly because it throws away the returned promise. Directly in the quote i provided above. – Kevin B Jan 19 '18 at 21:42
  • @KevinB No, it does not, at least not for the present question to have an acceptable answer. "throwing them away" is not an adequate answer. We would first need to clearly define what "throwing them away" or "throws away" technically means relevant to a specification. – guest271314 Jan 19 '18 at 21:42

1 Answers1

5

await suspends the current function until the Promise is resolved. When using multiple await calls in a for loop, they are all executed within the same block scope and, thus, wait for the previous one to finish before continuing.

When using the forEach function, each iteration of the loop is run in its own scope, so each await has no effect on the others.

user5664615
  • 400
  • 1
  • 10
  • 17