Ab initio front end --es6 (Promise)

Promise

concept

Promise is a solution for asynchronous programming, which is more reasonable and powerful than traditional solutions - callback functions and events.

The Promise is simply a container that holds the results of an event (usually an asynchronous operation) that will not end in the future.

characteristic

  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.

state

Promise object represents an asynchronous operation and has three states:

pending, completed, and rejected.

Only the result of asynchronous operation can determine the current state, and no other operation can change this state.

shortcoming

  1. Promise cannot be cancelled. Once it is created, it will be executed immediately. It cannot be cancelled halfway.
  2. If the callback function is not set, the error thrown by Promise will not be reflected to the outside.
  3. When it is in the pending state, it is impossible to know which stage it has reached (just started or about to be completed).

Note that for the convenience of the text, the resolved state later in this chapter only refers to the fully qualified state, not the rejected state.

usage

Writing js is no stranger to asynchronous events.

settimeout(()=>{
  console.log("123")
},0)

console.log("abc")
//Who output first?

I will not repeat the above questions

What if abc needs to output after 123 execution?

Of course, you can use callback, but it is a very desperate thing to use callback.

At this time: Promise, an object born for asynchronous programming, stands up

let p = new Promise((resolve,reject)=>{
  //Some asynchronous operations
  settimeout(()=>{
    console.log("123")
    resolve("abc");
  },0)
})
.then(function(data){
  //resolve status
  console.log(data)
},function(err){
  //reject status
})
//'123'
//'abc'

I'm tired of typing

At this time, you should have two questions: 1 Is there wool to wrap such a function? 2.resolve(‘123’); Is this dry wool?

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.

In other words, the state is determined by the execution of the parameters (functions) during instantiation. According to different states, see whether the first parameter or the second parameter of then needs to be taken.

The parameters of resolve() and reject() will be passed to the data or err of the corresponding callback function

Then returns a new Promise instance, that is, you can continue then

Usage of chain operation

Therefore, on the surface, Promise can only simplify the writing of layers of callbacks, but in essence, the essence of Promise is "state". The callback function can be called in time by maintaining and transferring the state. It is much simpler and more flexible than passing the callback function. Therefore, the correct scenario for using Promise is as follows:

runAsync1()
.then(function(data){
    console.log(data);
    return runAsync2();
})
.then(function(data){
    console.log(data);
    return runAsync3();
})
.then(function(data){
    console.log(data);
});
//Asynchronous task 1 execution completed
//Any data 1
//Asynchronous task 2 execution completed
//Whatever data 2
//Asynchronous task 3 execution completed
//Whatever data 3

runAsync1, runAsync2, runAsync3 long ↓

function runAsync1(){
    var p = new Promise(function(resolve, reject){
        //Do some asynchronous operations
        setTimeout(function(){
            console.log('Asynchronous task 1 execution completed');
            resolve('Any data 1');
        }, 1000);
    });
    return p;            
}
function runAsync2(){
    var p = new Promise(function(resolve, reject){
        //Do some asynchronous operations
        setTimeout(function(){
            console.log('Asynchronous task 2 execution completed');
            resolve('Whatever data 2');
        }, 2000);
    });
    return p;            
}
function runAsync3(){
    var p = new Promise(function(resolve, reject){
        //Do some asynchronous operations
        setTimeout(function(){
            console.log('Asynchronous task 3 execution completed');
            resolve('Whatever data 3');
        }, 2000);
    });
    return p;            
}

In the then method, you can also directly return data instead of Promise object, and you can also receive data in the following then:

runAsync1()
.then(function(data){
    console.log(data);
    return runAsync2();
})
.then(function(data){
    console.log(data);
    return 'Direct return data';  //Data is returned directly here
})
.then(function(data){
    console.log(data);
});
//Asynchronous task 1 execution completed
//Any data 1
//Asynchronous task 2 execution completed
//Whatever data 2
//Direct return data

Usage of reject

In the previous examples, there are only "successful" callbacks, but no "failed" callbacks. The function of reject is to set the Promise status to rejected, so that we can catch it in then and then execute the callback in the "failed" situation.

let num = 10;
let p1 = function() {
   	return new Promise((resolve,reject)=>{
      if (num <= 5) {
        resolve("<=5,go resolce")
        console.log('resolce Can't end Promise')
      }else{
        reject(">5,go reject")
        console.log('reject Can't end Promise')
      }
    }) 
}

p1()
  .then(function(data){
    console.log(data)
  },function(err){
    console.log(err)
  })
//reject cannot end Promise
//>5. Go reject

resolve and reject will always be executed at the end of the current environment, so the subsequent synchronization code will be executed first.

If there is still code to be executed after resolve and reject, it is best to put it in then.

Then write return before resolve and reject.

Promise.prototype.catch()

Promise. prototype. The catch method is An alias for then(null, rejection), which specifies the callback function when an error occurs.

p1()
  .then(function(data){
    console.log(data)
  })
  .catch(function(err){
  	console.log(err)
  })
//reject cannot end Promise
//>5. Go reject 	

Promise.all()

Promise. The all method is used to wrap multiple promise instances into a new promise instance.

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

The state of p is determined by p1, p2 and p3, which can be divided into two cases.

  1. Only when the states of p1, p2 and p3 become fully, the state of p will become fully. At this time, the return values of p1, p2 and p3 form an array and are passed to the callback function of p.
  2. As long as one of p1, p2 and p3 is rejected, the status of p becomes rejected. At this time, the return value of the first rejected instance will be passed to p's callback function.

promises is an array containing three promise instances. Promise will be called only when the status of these three instances becomes fully or one of them becomes rejected Callback function after the all method.

If the catch method is defined for the Promise instance as a parameter, once it is rejected, Promise will not be triggered If the catch method of all () has no parameters and does not define its own catch, Promise will be called Catch method of all().

Promise.race()

Promise. The race method also packages multiple promise instances into a new promise instance.

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

In the above code, as long as one instance of p1, p2 and p3 changes the state first, the state of p will change accordingly. The return value of the Promise instance that changed first is passed to the callback function of p.

Promise.resolve()

Sometimes you need to convert an existing object into a Promise object, Promise The resolve method does this.

const jsPromise = Promise.resolve('123');

The above code turns 123 into a Promise object.

Promise.resolve is equivalent to the following.

Promise.resolve('123')
// Equivalent to
new Promise(resolve => resolve('123'))

Promise. The parameters of the resolve method are divided into four cases.

  1. Parameter is a Promise instance

    If the parameter is a Promise instance, Promise Resolve will return the instance intact without any modification.

  2. Parameter is a thenable object

    thenable object refers to the object with then method, such as the following object.

    let thenable = {
      then: function(resolve, reject) {
        resolve(42);
      }
    };
    
    

    Promise. The resolve method turns this object into a promise object, and then immediately executes the then method of the thenable object.

    let thenable = {
      then: function(resolve, reject) {
        resolve(42);
      }
    };
    
    let p1 = Promise.resolve(thenable);
    p1.then(function(value) {
      console.log(value);  // 42
    });
    
    

    In the above code, after the then method of thenable object is executed, the state of object p1 changes to resolved, so the callback function specified by the last then method is executed immediately and output 42.

  3. The parameter is not an object with a then method, or it is not an object at all

    Promise. If the parameter is a raw value or an object without a then method The resolve method returns a new promise object with the status of resolved.

    const p = Promise.resolve('Hello');
    
    p.then(function (s){
      console.log(s)
    });
    // Hello
    
    

    The above code generates a new promise object instance p. Since the string Hello does not belong to an asynchronous operation (the judgment method is that the string object does not have the then method), the status of the returned promise instance is resolved, so the callback function will be executed immediately. Promise. The parameters of the resolve method will be passed to the callback function at the same time.

  4. Without any parameters

    Promise. The resolve method allows you to directly return a promise object in the resolved state without parameters.

    Therefore, if you want to get a Promise object, a more convenient method is to call Promise directly Resolve method.

    const p = Promise.resolve();
    
    p.then(function () {
      // ...
    });
    
    

    The variable p in the above code is a Promise object.

    It should be noted that the Promise object of immediate resolve is at the end of this round of event loop, not at the beginning of the next round of event loop.

    setTimeout(function () {
      console.log('three');
    }, 0);
    
    Promise.resolve().then(function () {
      console.log('two');
    });
    
    console.log('one');
    
    // one
    // two
    // three
    
    

    In the above code, setTimeout(fn, 0) is executed at the beginning of the next "event loop", promise Resolve() is executed at the end of this round of "event loop", console Log ('one ') is executed immediately, so it is output first.

    Promise.reject()

    Promise. The reject (reason) method will also return a new promise instance with the status of rejected.

    const p = Promise.reject('Error ');
    // Equivalent to
    const p = new Promise((resolve, reject) => reject('Error '))
    
    p.then(null, function (s) {
      console.log(s)
    });
    // Error 
    
    

    The above code generates an instance p of the Promise object with the status of rejected, and the callback function will be executed immediately.

    Note promise The parameters of the reject () method will be used as the reason for reject and become the parameters of subsequent methods. This is similar to promise The resolve method is inconsistent.

    const thenable = {
      then(resolve, reject) {
        reject('Error ');
      }
    };
    
    Promise.reject(thenable)
    .catch(e => {
      console.log(e === thenable)
    })
    // true
    
    

    In the above code, promise The parameter of the reject method is a thenable object. After execution, the parameter of the catch method is not the "error" string thrown by reject, but the thenable object.

Keywords: Javascript Front-end ECMAScript React

Added by allinurl on Mon, 17 Jan 2022 20:43:04 +0200