Promise to introduce

Promise’s asynchronous programming solution, which is more rational and powerful than the traditional solution (callback functions), is designed to solve the problem of callback hell.

What is callback hell? Look at the following code:

doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Get the final result:' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);
Copy the code

Reading the code above, isn’t it hard, makes for a classic callback hell.

Now rewrite the above code with Promise:

doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Get the final result:' + finalResult);
})
.catch(failureCallback);
Copy the code

The characteristics of

  1. The state of an object is unaffected. A Promise object represents an asynchronous operation and has three states:

    Pending: Pending. This will be very depressing

    Only the result of an asynchronous operation can determine the current state, which cannot be changed by any other operation.

  2. Once the state changes, it doesn’t change again, and it can happen any time.

The state of a Promise object can change from Pending to Resolved and from Pending to Rejected. So as long as these two things happen, it’s frozen, it’s not going to change anymore, it’s going to stay that way. If you add a callback to a Promise object even after the change has occurred, you get this result immediately. This is completely different from events, which have the characteristic that if you miss it and listen again, you don’t get the result.

advantages

  • The chain operation reduces the coding difficulty
  • Code readability is significantly improved

disadvantages

  • You cannot cancel a Promise, it is executed as soon as it is created, and you cannot cancel it in mid-stream.
  • If the callback function is not set, the errors thrown by the Promise internally are not reflected externally.
  • When you are in the Pending state, you have no way of knowing where you are (just started or about to finish).

Instance methods

(1) Then is the callback function when the instance state changes. The first argument is the callback function when the instance state changes and the second argument is the callback function when the instance state changes and the second argument is the callback function when the instance state changes

(2) The then method returns a new Promise instance, which is why promises can be chained

getJSON("/posts.json").then(function(json) {
  return json.post;
}).then(function(post) {
  // ...
});
Copy the code

(3) the catch

The catch() method is an alias for.THEN (null, rejection) or.then(undefined, rejection) and is used to specify the callback function when an error occurs

getJSON('/posts.json').then(function(posts) {
  // ...
}).catch(function(error) {
  // Handle the error that occurred when getJSON and the previous callback function were running
  console.log('An error occurred! ', error);
});
Copy the code

(4) finally ()

The finally() method is used to specify an action that will be performed regardless of the final state of the Promise object

promise
.then(result= >{...}). The catch (error= >{...}). Finally,() = > {···});
Copy the code

Constructor method

(1) The all Promise.all() method is used to wrap multiple Promise instances into a new one

const p = Promise.all([p1, p2, p3]);
Copy the code

Take an array (iteration object) as an argument, and the array members should all be Promise instances

The status of instance P is determined by P1, P2, and P3 and is divided into two types:

  • This is fulfilled only when the states of P1, p2 and p3 are fulfilled. In this case, the return values of P1, p2 and p3 form an array and are passed to the callback function of P
  • If either P1, P2, or P3 is rejected, p becomes rejected and the return value of the first rejected instance is passed to the p callback function

Note that if a Promise instance has its own catch method defined, it does not emit the catch method of Promise.all() once it is rejected

The race() promise.race () method also wraps multiple Promise instances into a new one

const p = Promise.race([p1, p2, p3]);
Copy the code

Whenever one instance of P1, P2, or P3 changes state first, the state of P changes accordingly

The return value of the first Promise instance changed is passed to p’s callback function

(3) The allSettled() promise.allsettled () method takes a set of Promise instances as parameters and wraps them into a new Promise instance

The wrapping of the instance will not end until all of these parameter instances have returned results, whether fulfilled or rejected

const promises = [
  fetch('/api-1'),
  fetch('/api-2'),
  fetch('/api-3')];await Promise.allSettled(promises);
removeLoadingIndicator();
Copy the code

(4) Resolve () Convert an existing object to a Promise object

Promise.resolve('foo')
/ / equivalent to the
new Promise(resolve= > resolve('foo'))
Copy the code

The parameters can be divided into four cases, as follows:

  • The parameter is a Promise instance, and promise.resolve returns the instance unchanged
  • The argument is a Thenable object, promise.resolve converts this object to a Promise object, and then executes the thenable object’s then() method immediately
  • If the argument is not an object with a THEN () method, or not an object at all, promise.resolve () returns a new Promise object in the resolved state
  • Return a Promise object in the resolved state when no parameters are specified

(5) Reject () promise. reject(reason) also returns a new Promise instance with the state rejected

const p = Promise.reject('Something went wrong');
/ / is equivalent to
const p = new Promise((resolve, reject) = > reject('Something went wrong'))

p.then(null.function (s) {
  console.log(s)
});
/ / make a mistake
Copy the code

Usage scenarios

Load the image as a Promise. Once the Promise is loaded, the state of the Promise changes

const preloadImage = function (path) {
  return new Promise(function (resolve, reject) {
    const image = new Image();
    image.onload  = resolve;
    image.onerror = reject;
    image.src = path;
  });
};
Copy the code

Through the chain operation, multiple render data is given to a then, let each do its own job. Or when the next asynchronous request depends on the result of the last request, we can also solve the problem amicably through a chain operation

// Each has its own job
getInfo().then(res= >{
    let { bannerList } = res
    // Render the rotograph
    console.log(bannerList)
    return res
}).then(res= >{
    
    let { storeList } = res
    // Render the store list
    console.log(storeList)
    return res
}).then(res= >{
    let { categoryList } = res
    console.log(categoryList)
    // Render the list of categories
    return res
})
Copy the code

All () is used to combine multiple requests and summarize all request results. You only need to set a loading

function initLoad(){
    // Load.show () // Load loading
    Promise.all([getBannerList(),getStoreList(),getCategoryList()]).then(res= >{
        console.log(res)
        loading.hide() / / close the loading
    }).catch(err= >{
        console.log(err)
        loading.hide()/ / close the loading})}// Data initialization
initLoad()
Copy the code

With RACE, you can set the image request timeout

// Request an image resource
function requestImg(){
    var p = new Promise(function(resolve, reject){
        var img = new Image();
        img.onload = function(){
           resolve(img);
        }
        //img.src = "https://b-gold-cdn.xitu.io/v3/static/img/logo.a7995ad.svg"; The correct
        img.src = "https://b-gold-cdn.xitu.io/v3/static/img/logo.a7995ad.svg1";
    });
    return p;
}

// The delay function is used to time the request
function timeout(){
    var p = new Promise(function(resolve, reject){
        setTimeout(function(){
            reject('Image request timeout');
        }, 5000);
    });
    return p;
}

Promise
.race([requestImg(), timeout()])
.then(function(results){
    console.log(results);
})
.catch(function(reason){
    console.log(reason);
});

Copy the code