JavaScript asynchronous solution Promise full parsing

What is a Promise?

Promise is a JS asynchronous programming solution that solves the problem of traditional asynchronous programming callback hell. Semantically: A Promise is an object that communicates asynchronous programming operation messages to the outside world.

Three states of Promise

A Promise object represents an asynchronous operation with three states:

  1. pending(In progress)
  2. fulfilled(Completed)
  3. rejected(Failed)

Only the result of an asynchronous operation can determine the current state, and no other operation can change it. Pending is the initial state, and there are only two kinds of state changes:

  1. pending -> fulfilled(Asynchronous task completed)
  2. pending -> rejected(Asynchronous task failed)

And once the state changes, the state freezes, and it doesn’t change anymore. This results in a Promise being executed as soon as it is created and cannot be cancelled.

Basic use of Promise

ES6 specifies that a Promise is a constructor that generates an instance of a Promise object.

const promise = new Promise(function(resolve,reject){
    // Asynchronous operation
    if(success){    // The asynchronous operation succeeded
        resolve(value);
    } else{         // The asynchronous operation failedreject(err); }})Copy the code

The parameter accepted by the Promise constructor is a function that has two arguments specified by the JS engine: the resolve and reject functions

  • resolveThe function does two things:
    1. Change the Promise state frompending -> fulfilled(Wait -> Succeed)
    2. Pass value, the result of the successful asynchronous operation, as a parameter. (Received by the then method)
  • rejectThe function also has two functions:
    1. Change the Promise state frompending -> rejected(Wait -> Fail)
    2. Error message that the asynchronous operation will failerrPass it as an argument. (From the followingthen /catchMethod receive)

Promise’s three instance methods then catch finally

1. Promise.prototype.then()

A Promise instance has a THEN method, which is defined on the prototype object. After a Promise instance is generated, you can use the THEN method to specify a callback function in the resolve and Rejected states respectively: get the state of the asynchronous operation inside the Promise.

promise.then(
  function (value) {
    console.log(value); This is fulfilled when the asynchronous operation is successful
  },
  function (err) {
    console.log(err); // Call when the asynchronous operation fails (rejected state)});Copy the code

The then method can take two callback functions as arguments:

The first callback is called when the Promise instance becomes fulfilled and takes the value passed by the resolve function. The second callback is called when the Promise instance becomes Rejected and takes the err parameter passed by the Reject function. The return value of the then method is a new Promise object, so.THEN can be chained.

2. Promise.prototype.catch()

The catch method of a Promise instance, which specifies the callback function when an error occurs, is the syntactic sugar of.then(null, rejection).

promise
  .then(function (val) {
    console.log(val); This is fulfilled when the asynchronous operation is successful
  })
  .catch(function (err) {
    console.log(err); // Call when the asynchronous operation fails (rejected state)
  });
Copy the code

In the above code, if the promise object state becomes fulfilled, the callback function specified by the THEN method is called. If the asynchronous operation throws an error, the state will be rejected and the callback function specified by the catch method will be called. In addition, the callback function specified by the THEN method is also caught by the catch method if an error is thrown.

promise
  .then((val) = > console.log("fulfilled:", val))
  .catch((err) = > console.log("rejected:", err));
/ / equivalent to the
promise
  .then((val) = > console.log("fulfilled:", val))
  .then(null.(err) = > console.log("rejected:", err));
Copy the code

If the Promise state has changed to Resolved, throwing an error is invalid. Once a Promise’s state changes, it stays in that state forever and never changes again. The error of a Promise object bubbles and is passed back until it is caught, meaning that the error is always caught by the next catch statement.

3. Promise.prototype.finally()

The finally method of a Promise instance is used to specify a function that will execute regardless of the final state. Is the syntax sugar for.then(function,function) (same as function).

promise.finally((message) = > console.log(The state has changed., message));
/ / equivalent to the
promise.then(
  (message) = > console.log(The state has changed., message),
  (message) = > console.log(The state has changed., message)
);
// Execute on success or failure
Copy the code

Promise’s two static methods, all and Race

1. Promise.all()

The promise. all(arr) method is a static method mounted on the Promise constructor. It takes an array of Promise objects, arr, and returns a Promise instance:

This instance will call the internal resolve function when the state of all the objects in the Promise array becomes fulfilled. This instance calls the Reject function when the state of any object in the Promise array becomes Rejected (reject takes the err of the first promiser). This is similar to the and operation (&&) in JS: return true if all expressions are true, and false if any expressions are false.

let p1 = new Promise((resolve,reject) = >{
resolve('p1-success'})),let p2 = new Promise((resolve,reject) = >{
resolve('p2-success'})),let p3 = new Promise((resolve,reject) = >{
reject('p1-error'})),Promise.all([p1,p2,p3]).then(val= >{
console.log(val)
}).catch(err= >{
console.log(err)
})

/ / output p1 - error
Copy the code

It is important to note that the array of successful results obtained by promise.all () is in the same order as the array received by promise.all (), that is, p1 comes first, even though P1 is obtained later than P2. This brings a huge benefit: while developing request data on the front end, promise.all () can certainly solve the problem of occasionally sending multiple requests and getting and using the data in the order of the requests.

2. Promise.race()

The promise.race (arR) method returns a Promise instance that will be resolved or rejected once one of the Promise objects in the ARR is resolved or rejected. A promise.race ([p1, P2, p3]) returns a result that is faster, regardless of whether the result itself is a success or a failure.

let p1 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    resolve("p1-success");
  }, 1000);
});
let p2 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    resolve("p2-success");
  }, 500);
});
let p3 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    reject("p3-error");
  }, 1000);
});

Promise.race([p1, p2, p3])
  .then((val) = > {
    console.log(val);
  })
  .catch((err) = > {
    console.log(err);
  });

/ / output p2 - success
Copy the code