Home > Article > Web Front-end > The ins and outs of async/await
Preface
During the interview, async/await is a good way to see the candidate's knowledge. Of course, I didn't think about what angle to explain this knowledge point. When asked by the interviewer, you can answer the syntax sugar of the self-executing generator. But have I realized it a little bit, or have I seen his realization?
How babel is implemented
Note: If you don’t know about generator, you can take a look at generator first, and by the way, you can take a look at iterator.
ex code:
async function t() { const x = await getResult(); const y = await getResult2(); return x + y; }
babel conversion code
"use strict"; function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } function t() { return _t.apply(this, arguments); } function _t() { _t = _asyncToGenerator(function* () { const x = yield getResult(); const y = yield getResult2(); return x + y; }); return _t.apply(this, arguments); }
As can be seen from the code, babel
converts a generator
For async
, two steps are used, _asyncToGenerator
and asyncGeneratorStep
.
_asyncToGenerator
What did
1. Calling _asyncToGenerator
returned a promise
, which happened to be consistent with async
Functions can be connected to then
features.
2. Define a successful method _next
and define a failed method _throw
. In the two functions, asyncGeneratorStep
is called. After reading asyncGeneratorStep
, you will know that this is actually a recursion.
3. Execute _next
. That is the self-executing generator mentioned above.
asyncGeneratorStep
What it did
1. Try-catch to capture errors during the execution of generator
. If an error is reported, the async
function will directly enter the reject
status.
2. Determine whether the done
value in info
is true. If true, it means that the iterator has been executed. You can resolve the value
go out. Otherwise, continue to call _next
to pass the value to the next one.
这里我唯一没有看明白的是`_throw`,这个看代码像是执行不到的。promise.resolve状态值应该是fulfilled。看懂的 可以在评论中和我说一下,感谢。
Advantages of async/await
Whenever a new syntactic sugar appears, it must make up for the shortcomings of the previous generation solution.
ex: The appearance of
promise is to avoid callback hell
. The way to avoid it is to chain calls.
What does async/await solve?
The necessity of replacing promise with async/await
Synchronous way of handling asynchronous
async/await is closer to synchronization style, while promise uses the then method. Compared with async/await, the code will become larger, and there is not much difference between async/await and synchronization functions. However, there is still a gap in the writing method of promise.
Promise and async/await code comparison
promise version
function getData() { getRes().then((res) => { console.log(res); }) }
async/await version
const getData = async function() { const res = await getRes(); console.log(res); }
Intermediate value
When using promises, you will find that when multiple promises are serialized, it is very difficult for the subsequent promise to obtain the value of the previous promise. And async solves this problem exactly.
Example of promise to obtain intermediate value
const morePromise = () => { return promiseFun1().then((value1) => { return promiseFun2(value1).then((value2) => { return promiseFun3(value1, value2).then((res) => { console.log(res); }) }) }) }
The above is a nested version, which may not be nested according to different needs.
const morePromise = () => { return promiseFun1().then((value1) => { return promiseAll([value1, promiseFun2(value1)]) }).then(([value1, value2]) => { return promiseFun3(value1, value2).then((res) => { console.log(res); }) }) }
There is less nesting level, but it is still not satisfactory.
Using async/await optimization example
const morePromise = async function() { const value1 = await promiseFun1(); const value2 = await promiseFun2(value1); const res = await promiseFun3(value1, valuw2); return res; }
Serial asynchronous processes must involve intermediate values, so the advantages of async/await are obvious.
The situation of conditional statements
For example, there is currently a requirement. After you have requested a piece of data, you can then determine whether you need to request more data. There will still be nested levels when implemented using promises.
const a = () => { return getResult().then((data) => { if(data.hasMore) { return getMoreRes(data).then((dataMore) => { return dataMore; }) } else { return data; } }) }
But using async to optimize this example can make the code more beautiful.
async/await optimization example
const a = async() => { const data = await getResult(); if(data.hasMore) { const dataMore = await getMoreRes(data); return dataMore; } else { return data; } }
Disadvantages of async/await
We have talked about some of the advantages of async/await above, but async/await is not omnipotent. . The above are all about serial asynchronous scenarios. When we turn into a parallel asynchronous scenario. It is still necessary to use promise.all to implement
Parallel asynchronous scenarios
const a = async function() { const res = await Promise.all[getRes1(), getRes2()]; return res; }
async/await error handling
async/await in error capture The main aspect is try-catch.
try-catch
const a = async () => { try{ const res = await Promise.reject(1); } catch(err) { console.log(err); } }
promise’s catch
You can extract a public function to do this. Because each promise is followed by catch processing, the code will be very lengthy.
const a = async function() { const res = await Promise.reject(1).catch((err) => { console.log(err); }) }
// 公共函数 function errWrap(promise) { return promise().then((data) => { return [null, data]; }).catch((err) => { return [err, null]; }) }
Recommended tutorial: "JS Tutorial"
The above is the detailed content of The ins and outs of async/await. For more information, please follow other related articles on the PHP Chinese website!