Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't the code after await run right away? Isn't it supposed to be non-blocking?

I have a hard time understanding how async and await works behind the scenes. I know we have promises which make our non blocking code by using the "then" function we can place all the work we need to do after the promise is resolved. and the work we want to do parallel to promise we just write it outside our then function. Hence the code becomes non blocking. However i don't understand how the async await makes non-blocking code.

async function myAsyncFunction() {   try {     let data = await myAPICall('https://jsonplaceholder.typicode.com/posts/1');     // It will not run this line until it resolves await.     let result = 2 + 2;     return data;   }catch (ex){     return ex;   } } 

See the above code. I cannot move forward until the API call is resolved. If it makes my code blocking code, how is it any better then promises? Or is there something I missed about async and await? Where do i put my code that is not dependent to the await call? so it can keep on working without await holding the execution?

I am adding a Promise code that i would like to replicate in an async await example.

function myPromiseAPI() {   myAPICall('https://jsonplaceholder.typicode.com/posts/1')     .then(function (data) {         // data     });    // runs parallel   let result = 2 + 2; } 
like image 576
Rohail Najam Avatar asked Apr 09 '17 02:04

Rohail Najam


People also ask

Does await cause blocking?

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.

Does await block next line of code?

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

Does code after await execute?

As you can see, the function code is run sequentially only until the first encountered await . Like with promises, it's up to the caller to decide if the code will be executed sequentially or not. If the caller doesn't make use of await (or then with promises), then your code won't run sequentially.

Does await block for loop?

No, await won't block the looping.

What is the difference between await and block in C++?

The whole point of await is to get the code to wait until the operation is done before continuing. The difference between this and blocking code is that the world outside the function can continue executing while the function is waiting for the asynchronous operations to finish.

Should I use await or task run for I/O?

A much better approach is to use await without Task.Run for I/O operations. This will have the same positive effect of keeping your application responsive, but without wastefully occupying additional threads/cores.

Is it possible to use async await in global state?

Since it’s not yet standard to use async await in a global state, I created a function run that wraps the code. Inside the .forEach function (now an async function) we call AIFoodRecognition with await and we print the result.

What does the await keyword DO in JavaScript?

Just as its name implies, the await keyword will cause the function to "wait" until its promise resolves before executing the next line. The whole point of await is to get the code to wait until the operation is done before continuing.


1 Answers

Just as its name implies, the await keyword will cause the function to "wait" until its promise resolves before executing the next line. The whole point of await is to get the code to wait until the operation is done before continuing.

The difference between this and blocking code is that the world outside the function can continue executing while the function is waiting for the asynchronous operations to finish.

async and await are just syntactic sugar on top of promises. They allow you to write code that looks a lot like ordinary synchronous code even though it uses promises under the covers. If we translated your example there to something that explicitly worked with the promises, it would look something like:

function myAsyncFunction() {   return myAPICall('https://jsonplaceholder.typicode.com/posts/1')     .then(function (data) {        let result = 2 + 2;        return data;     })     .catch(function (ex) {         return ex;     }); } 

As we can see here, the let result = 2 + 2; line is inside a .then() handler, which means it's not going to execute until myAPICall() has resolved. It's the same when you use await. await just abstracts away the .then() for you.

One thing to bear in mind (and I think the point you're looking for) is that you don't have to use await right away. If you wrote your function like this, then you could execute your let result = 2 + 2; line right away:

const timeout =       seconds => new Promise(res => setTimeout(res, seconds * 1000));    function myAPICall() {    // simulate 1 second wait time    return timeout(1).then(() => 'success');  }    async function myAsyncFunction() {    try {      console.log('starting');        // just starting the API call and storing the promise for now. not waiting yet      let dataP = myAPICall('https://jsonplaceholder.typicode.com/posts/1');        let result = 2 + 2;        // Executes right away      console.log('result', result);        // wait now      let data = await dataP;        // Executes after one second      console.log('data', data);        return data;    } catch (ex) {      return ex;    }  }    myAsyncFunction();

After some clarification, I can see that what you really wanted to know about is how to avoid having to wait for two async operations one by one and instead have them execute in parallel. Indeed, if you use one await after the other, the second won't start executing until the first has finished:

const timeout =       seconds => new Promise(res => setTimeout(res, seconds * 1000));    function myAPICall() {    // simulate 1 second wait time    return timeout(1).then(() => 'success');  }    async function myAsyncFunction() {    try {      console.log('starting');        let data1 = await myAPICall('https://jsonplaceholder.typicode.com/posts/1');      // logs after one second      console.log('data1', data1);        let data2 = await myAPICall('https://jsonplaceholder.typicode.com/posts/2');      // logs after one more second      console.log('data2', data2);    } catch (ex) {      return ex;    }  }    myAsyncFunction();

To avoid this, what you can do is start both async operations by executing them without awaiting them, assigning their promises to some variables. Then you can await both promises:

const timeout =       seconds => new Promise(res => setTimeout(res, seconds * 1000));    function myAPICall() {    // simulate 1 second wait time    return timeout(1).then(() => 'success');  }    async function myAsyncFunction() {    try {      console.log('starting');      // both lines execute right away      let dataP1 = myAPICall('https://jsonplaceholder.typicode.com/posts/1');      let dataP2 = myAPICall('https://jsonplaceholder.typicode.com/posts/2');        let data1 = await dataP1;      let data2 = await dataP2;        // logs after one second      console.log('data1', data1);      console.log('data2', data2);    } catch (ex) {      return ex;    }  }    myAsyncFunction();

One alternative way to do this is to use Promise.all() with some array decomposition:

const timeout =       seconds => new Promise(res => setTimeout(res, seconds * 1000));    function myAPICall() {    // simulate 1 second wait time    return timeout(1).then(() => 'success');  }    async function myAsyncFunction() {    try {      console.log('starting');        // both myAPICall invocations execute right away      const [data1, data2] = await Promise.all([          myAPICall('https://jsonplaceholder.typicode.com/posts/1'),           myAPICall('https://jsonplaceholder.typicode.com/posts/2'),      ]);        // logs after one second      console.log('data1', data1);      console.log('data2', data2);    } catch (ex) {      return ex;    }  }    myAsyncFunction();
like image 140
JLRishe Avatar answered Sep 26 '22 03:09

JLRishe