sal3jfc
sal3jfc

Reputation: 777

JS: what is async/await benefit when calling api?

how can async/await be used when calling APIs where the data you're fetching is dependent on the rest of the function content under it?
What if the fake API calls here pushed more names to the array? The updateNames function would be called already before the api calls would be done. Wouldn't I want to block the runtime in this case and make it synchronous?

 let names = [];

async foo() {
      
     await Promise.all[
         this.callAPI1();
         this.callAPI2();
     ]

     this.updateNames(names);
}

Upvotes: 0

Views: 1798

Answers (2)

ShadowRanger
ShadowRanger

Reputation: 155734

What if the fake API calls here pushed more names to the array? The updateNames function would be called already before the api calls would be done.

updateNames would not be called until both of the callAPI# functions completed; the await makes the code block (yielding control back to the event loop) until both promises (explicitly created or implicit when the functions are async themselves) complete.

If the functions in question don't return promises, executing synchronously/eagerly, then the await Promise.all([...]) is pointless (there were no promises involved), but there's still no risk of updateNames being called before the callAPI# calls finish; either:

  1. callAPI# returns a promise (in which case await blocks the current task until they complete, returning control to the event loop while it waits), or
  2. callAPI# does not return a promise and all the work is done immediately

and in either case, you can't get to updateNames before they finish.

Wouldn't I want to block the runtime in this case and make it synchronous?

You are blocking the current function call/task with the await. Other tasks scheduled on the event loop can run while the await is still blocked though, and that's the advantage to async processing. Every apparently asynchronous thing in JavaScript is sharing that event loop, and if you completely blocked (rather than awaiting an async call), none of them could run. This means, for example:

  1. setTimeout/setInterval calls don't fire
  2. UI drawing operations don't occur
  3. User input is blocked
  4. All events and observer handling code is deferred

Truly synchronous calls would make all of that (and more) wait until the entirety of foo completed. This is why async code is sometimes referred to as "cooperative multitasking"; control is never wrested away from the current task without its consent like you'd see in multithreaded code, instead control is handed back to the event loop voluntarily (via await) whenever a task is blocked waiting on asynchronous processing, or when the task completes. When the async task has a result, it waits for the event loop to hand control back to it, then continues where it left off.

Upvotes: 1

clm.rb
clm.rb

Reputation: 26

In your example, this.updateNames will be executed after your API calls are resolved because you have the await keyword and it is the same as doing:

Promise.all([call1(), call2()]).then(() => { this.updateNames() })

If you have any doubt you can always try by simulating an API call with a promisified setTimeout and some console.log:

const simulateAsync = () => {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log("resolved");
      resolve();
    }, 100);
  });
};

async function test() {
  await Promise.all([simulateAsync(), simulateAsync()]);

  console.log("after");
}

test();

Upvotes: 1

Related Questions