3 ms·
Long rant is long, so I’ll leave a tl;dr: regardless of how you feel about the syntactic sugar aspect, async/await has a runtime advantage of suspending the sta
by eyelidlessness 5y ago
Long rant is long, so I’ll leave a tl;dr: regardless of how you feel about the syntactic sugar aspect, async/await has a runtime advantage of suspending the stack rather than exiting early, which is (IMO) of greater benefit than the syntactic improvement.
- - -
I’m in the process of gradually moving several decade-old JS projects from explicit Promise APIs to async/await. The reason for this is not the syntactic sugar (although that’s quite a benefit, and I disagree wholeheartedly with the article on that point). The reason is that, at least with native Promises, the actual runtime behavior of async/await is considerably better. Because await suspends the stack, where .then/.catch enter a new stack frame.
I do see this has been discussed some in another thread, but I feel like it deserves more direct attention. It’s true that you can use libraries like Bluebird or whatever to get more accurate stack traces. But this is done by tracking Promise chains in user space. This is fine but it comes with a cost. Even if the library is quite fast (as Bluebird is), you still incur the cost of downloading and parsing it. Especially on HN where JS bloat is a daily topic, I’d hope this can be appreciated.
In my case, this cost wouldn’t be worth it even if the Promise API were clearly better. These projects need to run efficiently on low power mobile devices with limited connectivity. And we need to be able to diagnose runtime errors to address outstanding bugs. A library is a non-starter, and native Promise APIs actively hinder progress. The behavior of async/await is clearly superior.
Suspending the stack, either with async/await or generators, affords significantly better debugging capabilities. It allows Error stacks and console.trace to take better advantage of source maps.
It‘s also a much better optimization target for browsers. This isn’t just academic: even if async/await is semantically equivalent to Promise, it’s not a guarantee that the underlying .then/.catch will even be called if there’s no explicit Promise in the code. I’ve seen cases where they’re not, which was baffling until I understood (and this is how I came to understand) the difference in runtime behavior.