Monday, November 5, 2018

Async/await

There’s a special syntax to work with promises in a more comfortable fashion, called “async/await”. It’s surprisingly easy to understand and use.

Async functions

Let’s start with the async keyword. It can be placed before a function, like this:
async function f() {
  return 1;
}
The word “async” before a function means one simple thing: a function always returns a promise. If the code has return <non-promise> in it, then JavaScript automatically wraps it into a resolved promise with that value.
For instance, the code above returns a resolved promise with the result of 1, let’s test it:
async function f() {
  return 1;
}

f().then(alert); // 1
…We could explicitly return a promise, that would be the same:
async function f() {
  return Promise.resolve(1);
}

f().then(alert); // 1
So, async ensures that the function returns a promise, and wraps non-promises in it. Simple enough, right? But not only that. There’s another keyword, await, that works only inside async functions, and it’s pretty cool.

Await

The syntax:
// works only inside async functions
let value = await promise;
The keyword await makes JavaScript wait until that promise settles and returns its result.
Here’s example with a promise that resolves in 1 second:







async function f() {

  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("done!"), 1000)
  });

  let result = await promise; // wait till the promise resolves (*)

  alert(result); // "done!"
}

f();
The function execution “pauses” at the line (*) and resumes when the promise settles, with resultbecoming its result. So the code above shows “done!” in one second.
Let’s emphasize: await literally makes JavaScript wait until the promise settles, and then go on with the result. That doesn’t cost any CPU resources, because the engine can do other jobs meanwhile: execute other scripts, handle events etc.
It’s just a more elegant syntax of getting the promise result than promise.then, easier to read and write.
Can’t use await in regular functions
If we try to use await in non-async function, that would be a syntax error:



function f() {
  let promise = Promise.resolve(1);
  let result = await promise; // Syntax error
}
We can get such error in case if we forget to put async before a function. As said, await only works inside async function.


Summary

The async keyword before a function has two effects:
  1. Makes it always return a promise.
  2. Allows to use await in it.
The await keyword before a promise makes JavaScript wait until that promise settles, and then:
  1. If it’s an error, the exception is generated, same as if throw error were called at that very place.
  2. Otherwise, it returns the result, so we can assign it to a value.
Together they provide a great framework to write asynchronous code that is easy both to read and write.
With async/await we rarely need to write promise.then/catch, but we still shouldn’t forget that they are based on promises, because sometimes (e.g. in the outermost scope) we have to use these methods. Also Promise.all is a nice thing to wait for many tasks simultaneously.

No comments:

Post a Comment