JS: Asynchronous programming
Theory: Async/Await
Despite all the conveniences, promises are not the pinnacle of programming evolution. Let's look at the drawbacks they add:
- It has its error handling, which bypasses try/catch. It means that both types of error handling appear in the code in odd combinations.
- Sometimes, you need to pass data down the chain from the highest levels, and it's not very convenient to do that with promises. We need to create variables outside the promise
- It's still easy to end up with nested code when using promises if you're not paying attention.
All of these problems can be solved by the async/await mechanism, which makes code with promises look even more like synchronous code.
Let's recall our task of merging two files:
Now let's look at the same code using async/await. Note that async/await works with promises:
This version looks almost exactly like the synchronous version. The code is so simple, it's hard to believe it's not synchronous. Let's break it down step by step.
The first thing we see is the keyword async before the function definition. It means that this function always returns a promise: const promise = unionFiles(...). And now we don't need to return the result of this function explicitly, it will become a promise anyway.
The keyword await is used inside the function before calling functions that also return promises. If the result of this call is assigned to a variable or constant, the result of the call is written to it. If there is no assignment to a variable or constant, as in the last await call, then the operation waits to be executed without using its result.
As with the promises, asynchrony in this case guarantees that the program won't lock up while waiting for calls to complete. It can continue doing something else, but not in this function. But it does not guarantee that things will happen in parallel.
Also, successive await calls within the same function always run in strict order. The easiest way to understand this is to think of the code as a chain of promises, where each successive operation takes place inside then.
What about error handling? Now all you have to do is add the usual try/catch and it catches the errors:
However, when executing promises in parallel, you can't do without the Promise.all function:
In conclusion, the async/await mechanism makes the code as flat and synchronous as possible. It makes it possible to use try/catch and easily manipulate data from asynchronous operations:

