Home  >  Article  >  Web Front-end  >  The ins and outs of async/await

The ins and outs of async/await

hzc
hzcforward
2020-06-15 09:53:162676browse

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.

_asyncToGeneratorWhat 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.

asyncGeneratorStepWhat 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!

Statement:
This article is reproduced at:juejin.cn. If there is any infringement, please contact admin@php.cn delete