promise & axios & async/await

Time:2022-1-9

About promise, we still talk about his understanding from three aspects: what, why and how

【1】 What is promise

Promise is a solution for asynchronous programming in ES6, which is more reasonable and powerful than the traditional solution – callback functions and events.
In short, promise is a container that holds the results of an event (usually an asynchronous operation) that will not end in the future. Syntactically speaking, promise is an object from which you can get the message of asynchronous operation. Promise provides a unified API, and various asynchronous operations can be processed in the same way.
There are three states: pending, resolved and rejected. The feature is that only the result of asynchronous operation can determine which state it is currently. Once the state is changed, it cannot be changed again;

Promise common methods:

1. Class method (static method):
(1) Resolved: a promise object is returned in the success status;
(2) Reject: return a promise object in failure status;
(3) Race: multiple promise tasks are executed at the same time, and the result of the promise task that ends first is returned, regardless of whether the promise result is successful or failed;
(4) All: if all tasks are executed successfully, the execution results of all promise tasks are returned in the form of array. If there is an error, the result of reject is returned;
2. Example method:
(1). Then: its function is to add a callback function when the state changes for promise instance. As mentioned earlier, the first parameter of the then method is the callback function in the resolved state, and the second parameter is the callback function in the rejected state. They are optional
(2). Catch: exception handling;
(3). Finally: the operation that will be performed regardless of the final state of the promise object, success or failure

Promise features

1. The state of the object is not affected by the outside world.
2. Once the state changes, it will not change again. This result can be obtained at any time. This is completely different from the event. The characteristic of the event is that if you miss it and listen again, you will not get the result.

Promise disadvantages

1. Once it is executed, it cannot be cancelled halfway. Multiple then can be called in a chain, and the middle cannot jump out at will
2. The error cannot be captured externally and can only be pre judged internally. If the callback function is not set, the error thrown inside promise will not be reflected externally
3. It is difficult to monitor how promise is implemented internally. When it is in pending status, it is impossible to know which stage it is currently in (just started or about to be completed)

For these reasons, ES7 introduces more flexible async and await to handle asynchrony, which we will talk about later

【2】 Why promise

When a request is encountered in business, it depends on the result of the previous request. If the nesting of multiple layers of callback functions is called “callback region”, the code is not beautiful and not easy to maintain, so promise’s chain call can solve this problem

promise  & axios & async/await

image.png

【3】 How to use promise

//ES6 specifies that promise object is a constructor used to generate promise instances.

const promise = new Promise();

//The parameter of promise constructor is a function whose two parameters are resolve and reject. Resolve and reject are also functions provided by the JavaScript engine. You don’t need to define these two functions yourself.

promise  & axios & async/await

image.png

The built-in resolve function is used to change the state of promise object from incomplete to successful (i.e. from pending to resolved), call it when the asynchronous operation is successful, and pass the result of the asynchronous operation as a parameter; Resolve () can be used to pass parameters to then

The built-in reject function is used to change the state of the promise object from incomplete to failed (that is, from pending to rejected), call it when the asynchronous operation fails, and pass the error reported by the asynchronous operation as a parameter.

Promise example:

const promise = new Promise(function(resolve, reject) {
   // ... some code
   If (/ * asynchronous operation succeeded * /){
     resolve(value);// Call the built-in resolve function
   } else {
     reject(error);// Call the built-in reject function
   }
});
Or write it as an arrow function
const promise = new Promise((resolve, reject)=> {
   // ... some code
   If (/ * asynchronous operation succeeded * /){
     resolve(value);// Call the built-in resolve function
   } else {
     reject(error);// Call the built-in reject function
   }
});

After the promise instance is generated, you can use the then method to specify the callback functions in the resolved state and the rejected state respectively.

const promise = new Promise();
promise.then();

The then method can accept two callback functions as parameters. The first is the callback function in the resolved state, and the second is the callback function in the rejected state. These two functions are optional and not required. They all accept the value from the promise object as a parameter.

The essence of then chaining is to pass down and return a new promise, that is, then receives the promise returned in the previous step in the next step. Understanding this is very important for the following details!!

let promise = new Promise(function(resolve, reject) {
  // ... some code
  let name='jack'

  if(name=='jack'){
  // if (name!='jack'){
     Resolve ('succeeded '+ name)// Call the built-in resolve function
  }else{
     Reject ('failed '+ name)// Call the built-in reject function
  }
});

promise.then(function(value) {
    //Success - this is the callback function for the resolved state
    console. Log (value) // success, Jack
}, function(error) {
    //Failed - this is the callback function for the rejected state
    console. Log (error) // failed, Jack
});
Core usage: chain call

The promise instance uses the then method to return a new promise instance (note that it is not the original promise instance). And because every promise instance has Then method, so it can be written in a chain, that is, another then method can be called after the then method.
Using the chained then, you can call the callback function in order. The latter then will decide whether to take the successful callback or failed callback of the next then according to the status (success / failure) of the promise object returned after the previous then

const promise = new Promise((resolve, reject)=> {
   // ... some code
});
promise.then().then().then()...
//For example, the "success" string is output after 1 second
const MyPromise=function(time){
    let promise = new Promise(function(resolve, reject){
        //Do some asynchronous operations
        setTimeout(function(){
            Resolve ('success');
        }, time);
    });
    return promise;            
}
//Complete three-tier chain call
MyPromise().then(function(succesData) {
    //The first callback of the first then is successful
    console. Log ('result is' + succesdata);
},function(errorData) {
    //The first callback in the first then is successful
    console. Error ('error ', errordata);
}).then(function(succesData) {
    //The first callback of the second then is successful
    console. Log ('result is' + succesdata);
},function(errorData) {
    //The first callback in the second then is successful
    console. Error ('error ', errordata);
}).then(function(succesData) {
    //The first callback of the third then is successful
    console. Log ('result is' + succesdata);
},function(errorData) {
    //The first callback in the third then is successful
    console. Error ('error ', errordata);
});

Because The two function parameters in then are not necessary. Generally, only the first successful callback is written. Someone wants to ask, since there are so many promise objects and so many then, do I need to write a lot of catches to catch errors?
Of course, the answer is: no!, There is no such troublesome writing method. You only need to catch at the end, because the error handling of chain writing has the characteristic of “bubbling”. If there is a problem in any link in the chain, it will be caught, and the code behind a link will not be executed. So you can rewrite the above simplification into

//Simplify the three-tier chain call and change it to arrow function
MyPromise(1000).then(function(succesData) {
    //Modify it
    succesData=succesData+"1"
    //Successful callback of the first then
    console. Log ('data obtained by the first then: '+ succesdata);
    return succesData
}).then(function(succesData) {
    //Modify it
    succesData=succesData+"2"
    //Successful callback of the second then
    console. Log ('data obtained by the second then: '+ succesdata);
    return succesData
}).then(function(succesData) {
    //Modify it
    succesData=succesData+"3"
    //Successful callback of the third then
    console. Log ('data obtained by the third then: '+ succesdata);
    return succesData
}). Catch ((ERR) = > {// move to the first chain here. It is found that the above is not executed. Continue to execute the following
  console.log(err);
})

Promise's then chain call is still layer upon layer dependent logic, but it is not as ugly and difficult to maintain as "hell callback"
promise  & axios & async/await

image.png

promise & axios

Axios is an HTTP library encapsulated by promise. Axios itself is a promise. So we also inherit some methods, such as then

promise  & axios & async/await

image.png

For example, in Axios, we can also use then’s chain call instead of callback hell. Note that return is a promise object before it can continue to be used then

created(){
      this.$axios({
        method: 'post',
        dataType: 'json',
        url: '/customer/selectListByPage',
        data:{}
      }).then(function (res) {
          //First floor
          console.log(res.data)
          //Return is required, otherwise the output will be undefined
          return res.data
      }).then(function (data) {
          //Second floor
          console.log(data)
          return data     
      }).then(function (data) {
          //Third floor
          console.log(data)
      }).catch((err)=>{
          console.log(err);
      })
  },

promise & async/await

Async / await came out of ES7 and is an upgraded version of promise of ES6. It can better handle then chain calls. Await, as its name implies, is’ wait a minute ‘(wait a minute after my promise asynchronously executes the following) to make asynchronous programming feel more synchronous. The simple understanding is that the await asynchrony in the async declared function will be executed synchronously.

[features]
(1) The return of async declared function is essentially a promise, so it can be used then
(2) Async must declare a function, so await must be used inside the function declared by the current async (and cannot be used in its child functions). The two are used together.

(3) Await, as its name implies, is to wait for a while. If and only if await declares a promise and does not return a value, the following program will not be executed!!! Make asynchronous programming feel more synchronous.

Common methods of declaring async:
//Function declaration
async function foo() {}
//Function expression
const foo = async function () {};
//Arrow function
const foo = async () => {};

For example, printing is not executed until 3 seconds later. Asynchronous code but synchronous feel. This is exactly the effect that async / await cooperates with promise

const demo = async ()=>{
    //Await declares that only a promise can realize asynchronous synchronous execution
    let result = await new Promise((resolve, reject) => {
      setTimeout(()=>{
        //do something
      }, 3000)
    });
    console. Log ('I'll print after the program above "I'll wait a minute");
    Return 'I am the return value';
}
//The return value of async, no matter what type, is essentially a promise, so it can be used then
demo().then(result=>{
    console. Log ('output: ', result)// I delayed the output by one second
}).catch((err)=>{ 
    console.log(err);
})

The same code as above, except that there is not a promise behind await, the printing is directly executed, and the alert is not issued until 3 seconds later, so the asynchronous code can be executed synchronously only after await is followed by a promise

const demo = async ()=>{
    //Await does not declare promise and cannot implement asynchronous synchronous execution
    let result = await setTimeout(()=>{
       //do something
       //Resolve ('I'm three seconds late ')
       alert(1)
    }, 3000)
    console. Log ('I'll print after the program above "I'll wait a minute");
    Return 'I am the return value';
}
//The return value of async, no matter what type, is essentially a promise, so it can be used then
demo().then(result=>{
    console. Log ('output: ', result)// I delayed the output by one second
}).catch((err)=>{ 
    console.log(err);
})

In the previous introduction to async / await, async / await is usually used with promise, and Axios is based on promise encapsulation, so we can use async / await and Axios together. On the Internet, many people put a layer of promise outside Axios, which is unscientific or do not understand the essence of Axios. You know: Axios is encapsulated by promise, and its essence is a promise, so there is no need to set a layer of promise

const demo =async () => {
        //The first asynchronous promise (Axios) interface requests data
        const result1 = await this.$axios({
          method: 'post',
          dataType: 'json',
          url: '/customer/selectListByPage', 
          data:{}
        })
        console.log(result1)
        //The second asynchronous promise (Axios) interface requests data
        const result2 = await this.$axios({
          method: 'post',
          dataType: 'json',
          url: '/customer/selectListByPage', 
          data:{}
        })
        console.log(result2)
        //The return value is essentially a promise
        return result1+result2
    }
    //Call
    demo().then(result=>{
      console. Log ('output: ', result); 
    }).catch((err)=>{ 
      console.log(err);
    })

It can also be written as

const getData1 = (data) => {
        //Return is required to ensure that await calls a promise in async
        return this.$axios({
          method: 'post',
          dataType: 'json',
          url: '/customer/selectListByPage', 
          data:{}
        })
    }
    const getData2 = (data) => {
        //Return is required to ensure that await calls a promise in async
        return this.$axios({
          method: 'post',
          dataType: 'json',
          url: '/customer/selectListByPage', 
          data:{}
        })
    }
    //Async / await instance
    const demo =async () => {
        //The first asynchronous promise (Axios) interface requests data
        const result1 = await getData1()
        console.log(result1)

        //The second asynchronous promise (Axios) interface requests data
        const result2 = await getData2()
        console.log(result2)

        //The return value is essentially a promise
        return result1+result2
    }
    //Call
    demo().then(result=>{
      console. Log ('output: ', result); 
    }).catch((err)=>{ 
      console.log(err);
    })