You know Async/await is syntactic sugar for generator and Promise, but is it just syntactic sugar? Is there a performance difference between the two, or promise.then() and await are both microtasks, but what is the order in which they are executed?

How does Async/await optimize stack processing for JavaScript engines

Yes, you read that right, as you can see from the title, async/await optimizes stack processing compared to Promise, that is, async/await performs better than Promise at this point

Using Async/Await not only improves the readability of your code, but also optimizes the way the JavaScript engine executes compared to using Promise directly

After ‘what’, let’s talk about ‘why’.

The biggest difference between Async/Await and Promise is that Await b() suspends the execution of the Async function it is in; Promise.then(b) adds the b function to the callback chain and continues to execute the current function. This difference is critical for the stack.

When a Promise chain throws an unhandled error, the JavaScript engine needs to print the error message and its stack, whether we use await b() or promise.then (b). The way they get the stack is different for the JavaScript engine.

Promise.then()

Look at the code below. Suppose b() returns a promise

const a = () => {
    b().then(() => c())
}
Copy the code

These things happen synchronously when a() is called, and b() produces a promise object that calls the then method. The promise will resolve at some point in the future, adding the then callback to the callback chain. If the async resolve function resolves, the scope of a() function will no longer exist. If the async resolve function resolves, the scope of a() function will not be paused. So how do you generate a stack containing a()? To solve this problem, the JavaScripts engine does some extra work; It logs and saves stack information in time. For the V8 engine, this stack information is passed along with the Promise in the Promise chain so that the C () function can retrieve the stack information if needed. But this undoubtedly incurs additional overhead, which degrades performance; Saving stack information takes up extra memory.

Await

We can do this with Async/await

const a = () => {
    await b()
    c()
}
Copy the code

When using await, there is no need to store stack information because it is sufficient to store Pointers from B () to a(). While b() is executing, a() is paused, so the scope of a() is still accessible in memory. If b() throws an error, the stack is quickly generated by a pointer. If the c() function throws an error, the stack information can be generated just like the synchronous function, because c() is executed in a(). Neither b() nor C () needs to store the stack information because the stack information can be generated immediately when needed. Storing Pointers is obviously more memory efficient than storing stacks

conclusion

Many ECMAScript syntactic features seem to be just syntactic sugar, but they are not, at least Async/await is more than syntactic sugar. For better performance in the way JavaScript engines handle stacks, try to use Async/await instead of directly using promises

  • Original text: mathiasbynens. Be/notes/async…
  • Mathias Bynens: Developer of the Google V8 engine
  • Free translation rather than literal translation

Check out the next article on the order of execution mentioned at the beginning of this article