6 Reasons Why JavaScript’s Async/Await Blows Promises Away
Why did I choose this article?
Front-end asynchronous problem handling has always been a difficult problem, from the despair of Callback Hell to the chaos of Promise/Deferred specifications, from Generator co to Async/Await changing the world. Why are asynchronous problems so hard to deal with, and to what extent can Async/Await solve the difficulties we encounter during development and debugging? I hope this article can give us some inspiration.
Of course, this is not a comprehensive overview of front-end asynchrony, but rather the advantages of Async/Await. However, this does not prevent us from starting from the characteristics of Async/Await, combining our own experience and lessons in the process of work and development, and seriously thinking and summarizing how to deal with asynchronous problems more gracefully and efficiently.
2 Content Summary
Advantages of Async/Await:
- Syntax concise and clear, save a lot of unnecessary anonymous functions
- Use try… catch… Handling exceptions
- Adding a conditional judgment is more intuitive
- Reduce unnecessary intermediate variables
- A more explicit error stack
- Breakpoints can be easily added to each asynchronous call during debugging
Limitations of Async/Await:
- Slows down the speed at which we read and understand code as previously seen
.then()
I know it’s asynchronous. Now I need to identify itasync
和await
The keyword - The current node.js version (Node 7) that supports Async/Await is not an LTS version, but the next LTS version will be released soon
It can be seen that most of the advantages of Async/Await mentioned in the article are from the aspect of improving the efficiency of development and debugging, and there are only two problems or limitations mentioned.
Let’s take a look at some of the in-depth opinions of the students who participated in the intensive reading:
This time, the students who put forward unique views are: @javie007 @manifold @Camsong @Turbe Xue @Light cang @Photo @Huang Ziyi.
Async/Await is not a new concept
Many students who participated in the intensive reading mentioned that Async/Await is not a new concept, and indeed it is.
As early as 2012, Microsoft officially introduced the concept of Async/Await when version 5.0 of C# language was released, and then Async/Await appeared successively in Python and Scala. After that, which is the protagonist of today’s discussion, ES 2016 formally proposed the Async/Await specification.
Here is an example code to use Async/Await in C# :
public async Task<int> SumPageSizesAsync(IList<Uri> uris) { int total = 0; foreach (var uri in uris) { statusText.Text = string.Format("Found {0} bytes ..." , total); var data = await new WebClient().DownloadDataTaskAsync(uri); total += data.Length; } statusText.Text = string.Format("Found {0} bytes total", total); return total; }
Copy the code
Let’s see how this works in JavaScript:
async function createNewDoc() {
let response = await db.post({}); // post a new doc
return await db.get(response.id); // find by id
}Copy the code
It is not hard to see that there is not much difference between the two purely asynchronous syntax. This is one of the reasons why Async/Await is getting a lot of praise and affection.
In fact, in the front-end field, there are also many classes of Async/Await implementation, one of which has to mention is wind. Js written by Lao Zhao, one of the famous Internet celebrities. From today’s point of view, the design and implementation of WindJS can be described as leading.
According to the description in the Async/Await specification – an Async function always returns a Promise – it is not hard to see the connection between Async/Await and Promise. This is why many students involved in intensive reading say that Async/Await is just a syntactic sugar.
Specifications are too boring to talk about, so let’s look at the actual code. Here is a basic Async/Await example:
async function test() {
const img = await fetch('tiger.jpg');
}Copy the code
After using Babel conversion:
'use strict';
var test = function() {
var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee() {
var img;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return fetch('tiger.jpg');
case 2:
img = _context.sent;
case 3:
case 'end':
return _context.stop(a); } } }, _callee,this);
}));
return function test() {
return _ref.apply(this.arguments); }; } ();function _asyncToGenerator(fn) {
return function() {
var gen = fn.apply(this.arguments);
return new Promise(function(resolve.reject) {
function step(key.arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
return Promise.resolve(value).then(function(value) {
step("next", value);
}, function(err) {
step("throw", err); }); }}return step("next");
});
};
}Copy the code
It is not hard to see that the Async/Await implementation is converted to a Promise based call. It is worth noting that a problem that could have been solved in three lines of code was converted into 52 lines of code, based on the fact that reGenerator already exists in the execution environment. The cost of code overhead has to be taken into account if it is to be used in Web environments where compatibility is not very good.
Is Async/Await really a better alternative
I don’t know if it’s a personal observation bias or if it’s a common belief. In the domestic front-end circles, there is not much interest in Async/Await. Several common views are: “It’s not promising syntactic sugar yet, it’s not interesting”, “Using CO is a perfect solution to asynchrony, no need to introduce any new concepts”, “the browser compatibility is so poor, compiling with Babel requires a lot of dependencies, it’s too expensive to use”, etc.
In this intensive reading, many students have pointed out the limitations of using Async/Await.
For example, using Async/Await does not support asynchronous concurrency well. Consider the case where a module needs to send three requests and get results before rendering, with no dependencies between the three requests. If Async/Await is used, write as follows:
async function mount() {
const result1 = await fetch('a.json');
const result2 = await fetch('b.json');
const result3 = await fetch('c.json');
render(result1, result2, result3);
}Copy the code
This is a lot simpler for asynchrony, but the three asynchrony requests are executed sequentially and don’t take full advantage of asynchrony. To implement true asynchrony, you still need to rely on promise.all to encapsulate a layer:
async function mount() {
const result = await Promise.all(
fetch('a.json'),
fetch('b.json'),
fetch('c.json'));render(.result);
}Copy the code
In addition, as mentioned above, async functions return a Promise by default, which means that async functions also encounter the same problem with promises: silently swallowing exceptions by default.
So while Async/Await can use try… catch… In this synchronization-compliant way of exception catching, you still have to manually add a try to each await call… catch… Otherwise, async returns a reject Promise.
Although the technology to deal with asynchronous problems is improving all the time, in actual engineering practice, we need asynchronous operation is also expanding and deepening, which is one of the reasons why various flow control libraries have been thriving.
In this reading, we affirm the advantages of Async/Await in processing asynchronous problems, but also mention some disadvantages in processing asynchronous problems:
- Lack of complex control flow, such as always, Progress, pause, resume, etc
- Missing interrupt method, unable to abort
Of course, some of these requirements may be less common from the perspective of the EMCA specification, but if they are included in the specification, it can also reduce the front-end programmer’s difficulty in choosing an asynchronous process control library.
3 summary
Async/Await is indeed the superior asynchronous processing solution, but we believe it is definitely not the ultimate processing solution. With the development of front-end engineering, there will be more, more complex and more sophisticated asynchronous problems, and there will also be solutions to cater to these problems, such as RxJS and JS-CSP mentioned by many students in intensive reading.
The discussion address is: asynchronous issues we dealt with in those years · Issue #6 · dt-fe/weekly
If you’d like to participate in the discussion, click here. There are new topics every week, published every Friday.