Annex 2: async/await

In actual development, there are always many asynchronous problems. The most common scenario is that after an interface request, you must wait for a period of time to get the result. If you encounter multiple interface dependencies, the problem becomes complicated. Everyone has been trying to use better solutions to these problems. At first, only callback functions could be used, and later some people started to use Promise thinking to get it done. In ES6, native Promise is supported and the Generator function is introduced.

Until ES7, there was async/await.

This is a solution to asynchronous problems with synchronous thinking.

I think many people may not be able to distinguish the difference between synchronous and asynchronous. If you have a thorough understanding of the event loop , you must have a good understanding of the concept of asynchrony. When we make a request, we will not wait for the response result, but will continue to execute the following code, and the processing of the response result will be resolved in the subsequent event loop. Then the meaning of synchronization is that the code will continue to execute after the result comes out.

We can use a two-person question-and-answer scenario as an analogy between asynchronous and synchronous. After A asks B a question, it does not wait for B's answer, and then asks the next question, which is asynchronous. After A asks B a question, he waits with a smile and waits for B to answer. After B answers, he will ask the next question. This is synchronization.

So let's remember this feature first and async/awaituse synchronous thinking to solve asynchronous problems.

Before continuing to analyze its syntax and usage, let's introduce how to support this syntax in our development environment.

Skip if you already know how to configure

async/await1. How to support syntax in your own development environment

There are mainly two methods here.

1. This syntax is supported in webpack

First download using npm in the current project babel-loader.

> npm install babel-loader --save-dev

Then configure it in the configuration file webpack.confing.dev.js, module.exports.module.rulesand add the following configuration elements to it.

  {
    test: /\.(js|jsx)$/,
    include: paths.appSrc,
    loader: require.resolve('babel-loader'),
    options: {
      cacheDirectory: true,
    },
  },

If you are using the latest version of create-react-app or vue-cli to build your code, they should already support this configuration.

2. This syntax is supported in gulp

First install the gulp plugin

> npm install gulp-babel --save-dev

then write the task

var gulp = require('gulp');
var babel = require('gulp-babel'); gulp.task('babel', function() { return gulp.src('src/app.js') .pipe(babel()) .pipe(gulp.dest('dist')); }); 

2. How to use

The async function is a syntactic sugar for Generator. It doesn't matter if you don't know what a Generator function is, we just need to know that the async function actually returns a Promise object.

async function fn() { return 30; } // 或者 const fn = async () => { return 30; } 

When declaring a function, prefix it with a keyword async, and this is how it is asyncused. When we console.logprint out the function fn declared above, we can see the following results:

console.log(fn());

// result
Promise = {
    __proto__: Promise,
    [[PromiseStatus]]: "resolved", [[PromiseValue]]: 30 } 

Obviously, the result of running fn is actually a Promise object. So we can also use then to handle subsequent logic.

fn().then(res => {
    console.log(res);  // 30
})

await means to wait. This means that the code needs to wait for the function behind await to finish running and have a return result before continuing to execute the following code. This is exactly the effect of synchronization.

But we need to note that the await keyword can only be used in async functions. And the function behind await must return a Promise object to achieve the effect of synchronization.

When we use a variable to receive the return value of await, the return value is the value resolved in Promise (that is, PromiseValue).

// 定义一个返回Promise对象的函数
function fn() { return new Promise((resolve, reject) => { setTimeout(() => { resolve(30); }, 1000); }) } // 然后利用async/await来完成代码 const foo = async () => { const t = await fn(); console.log(t); console.log('next code'); } foo(); // result: // 30 // next code 

Running this example, we can see that when an async function encounters an await, it will wait for the function behind the await to finish running, instead of executing it directly next code.

If we use the then method directly, to achieve the same result, we have to write the subsequent logic in the then method.

const foo = () => {
    return fn().then(t => {
        console.log(t);
        console.log('next code'); }) } foo(); 

Obviously, if async/await is used, the code structure will be more concise and the logic will be clearer.

exception handling

In Promise, we know that exceptions are caught by means of catch. And when we use async, the try/catchexception is caught by passing.

function fn() {
    return new Promise((resolve, reject) => { setTimeout(() => { reject('some error.'); }, 1000); }) } const foo = async () => { try { await fn(); } catch (e) { console.log(e); // some error } } foo(); 

If there are multiple await functions, only the first caught exception will be returned.

function fn1() {
    return new Promise((resolve, reject) => { setTimeout(() => { reject('some error fn1.'); }, 1000); }) } function fn2() { return new Promise((resolve, reject) => { setTimeout(() => { reject('some error fn2.'); }, 1000); }) } const foo = async () => { try { await fn1(); await fn2(); } catch (e) { console.log(e); // some error fn1. } } foo(); 
practice

In practice, the most asynchronous scenarios we encounter are interface requests, so here is an $.getexample in jquery to briefly show how to cooperate async/awaitto solve this scenario.

// 先定义接口请求的方法,由于jquery封装的几个请求方法都是返回Promise实例,因此可以直接使用await函数实现同步
const getUserInfo = () => $.get('xxxx/api/xx');

const clickHandler = async () => { try { const resp = await getUserInfo(); // resp为接口返回内容,接下来利用它来处理对应的逻辑 console.log(resp); // do something } catch (e) { // 处理错误逻辑 } } 

In order to ensure the integrity of the logic, it is try/catchessential in practice. In conclusion, programmers who don't handle error logic are not good programmers.

Compared with Promise, I personally think it async/awaithas a certain simplicity, but it is not an absolute advantage over Promise, so it can only be regarded as providing another equally great way. As for which way you choose to solve yourself after learning I think it's just a matter of personal preference.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324817938&siteId=291194637