Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In JavaScript, does using await inside a loop block the loop?

Take the following loop:

for(var i=0; i<100; ++i){     let result = await some_slow_async_function();     do_something_with_result(); } 
  1. Does await block the loop? Or does the i continue to be incremented while awaiting?

  2. Is the order of do_something_with_result() guaranteed sequential with regard to i? Or does it depend on how fast the awaited function is for each i?

like image 480
smerg Avatar asked Jun 07 '17 10:06

smerg


People also ask

Does async await block for loop?

You should make sure you never block the Event Loop. In other words, each of your JavaScript callbacks should complete quickly. This of course also applies to your await 's, your Promise.

Is await JavaScript blocking?

Though it creates a confusion, in reality async and await will not block the JavaScript main thread. Like mentioned above they are just syntactic sugars for promise chaining.

Does await blocks the next line?

await only blocks the execution of the next lines of code in an async function and doesn't affect the promise execution.

Does await block?

The await operator doesn't block the thread that evaluates the async method. When the await operator suspends the enclosing async method, the control returns to the caller of the method.


2 Answers

  1. Does await block the loop? Or does the i continue to be incremented while awaiting?

"Block" is not the right word, but yes, i does not continue to be incremented while awaiting. Instead the execution jumps back to where the async function was called, providing a promise as return value, continuing the rest of the code that follows after the function call, until the code stack has been emptied. Then when the awaiting is over, the state of the function is restored, and execution continues within that function. Whenever that function returns (completes), the corresponding promise -- that was returned earlier on -- is resolved.

  1. Is the order of do_something_with_result() guaranteed sequential with regard to i? Or does it depend on how fast the awaited function is for each i?

The order is guaranteed. The code following the await is also guaranteed to execute only after the call stack has been emptied, i.e. at least on or after the next microtask can execute.

See how the output is in this snippet. Note especially where it says "after calling test":

async function test() {      for (let i = 0; i < 2; i++) {          console.log('Before await for ', i);          let result = await Promise.resolve(i);          console.log('After await. Value is ', result);      }  }    test().then(_ => console.log('After test() resolved'));    console.log('After calling test');
like image 198
trincot Avatar answered Oct 08 '22 11:10

trincot


As @realbart says, it does block the loop, which then will make the calls sequential.

If you want to trigger a ton of awaitable operations and then handle them all together, you could do something like this:

const promisesToAwait = []; for (let i = 0; i < 100; i++) {   promisesToAwait.push(fetchDataForId(i)); } const responses = await Promise.all(promisesToAwait); 
like image 45
Kris Selbekk Avatar answered Oct 08 '22 12:10

Kris Selbekk