Promise chain usage details

This article focuses on the chain usage of promises.

1 Introduction

This article introduces the then, catch, finally methods and chain usage of promise objects. It focuses on the use of then and the execution process of chain calls.

 

If you don't know much about promises, you can check the preliminary article on promises-in the previous article.

2 Main content

•Then parameters and execution logic•then's return value•catch•finally•chain call logic

3 Promise instance method

In js, an object inherits methods from the prototype object of its constructor. E.g:

var arr = new Array();arr.push();

The above push method is actually a property in Array.protoType.

arr.push === Array.protoType.push ; // true

In the same way, a promise object will inherit methods from Promise.prototype.

•then()•catch()•finally()

4 The format and execution logic of then

The function of the then method is to add a callback function to the Promise object when the state changes. The following is an introduction from the three aspects of its call format, execution logic and return value

4.1 The format of then

It can write two parameters as follows:​​​​​​​

// p 是一个promise对象p.then(函数1[,函数2])

Both of its parameters are functions.

• The first parameter is the callback function of the resolved state. When the state of p changes from pending to resolved, function 1 will be executed. • The second parameter is the callback function of the rejected state. When the status of p changes from pending to rejected, function 2 will execute. •The second parameter is optional. If only one parameter is written, it is as follows:

promise对象.then(函数1)

4.2 Execution logic

Take the following code as an example​​​​​​​

var p = new Promise((resolve,reject)=>{
   
      resolve(val1);   // or reject(val2)})
p.then((okVal)=>{
   
       console.info("成功");    console.log(okVal);}, (errVal)=>{
   
       console.info("失败");    console.log(errVal);})

Its two parameters are functions, and its execution logic is:

• If the state of the promise object is resolved, then() will execute the first function and pass in the current PromiseValue (that is, val1 above); • If the state of the promise object is rejected, then() will execute the second A function and pass in the current PromiseValue (that is, val2 above);•In particular, if the state of the promise object is rejected and the then method does not set the second parameter at this time, an error will be thrown out, The wrong hint is about Uncaught (in promise).

Sample code 1​​​​​​​

var p = new Promise((resolve,reject)=>{
   
       //主动调用resolve,并传入1    resolve(1)})// 此时,P的状态是resolved,// 且值promiseValue 是1p.then((res)=>{
   
      // p的状态是resolved,执行then的第一个参数   // 把promisevalue传进来   console.log("then,ok",res)})

The execution output is:then,ok,1

Sample code 2​​​​​​​

var p = new Promise((resolve,reject)=>{
   
    //主动调用reject,并传入实参2   reject(2)})// 此时,P的状态是rejected,且值promiseValue 是2.p.then((res)=>{
   
      // p的状态是resolved   // 所以这句代码不会执行。   console.log("then,ok",res)},(err)=>{
   
    // p的状态是rejected // 执行then的第二个参数 // 并把promisevalue传进来。    console.log("then,err",err)})

The execution output is:then,err,2

4.3 The return value of then

The return value of the then() method is also a promise object, so it supports chain writing. But it should be noted that its return value is a new promise object, not the same object as the one that called the then method.

Take a look at the following code:​​​​​​​

var p1 = new Promise(()=>{});var p2 = p1.then(function f_ok(){},     function f_err(){}); // p2也是一个promise对象。
console.log(p1 === p2); // false

The above code can show that the result of p1.then() is a promise object different from p1.

 

In other words, then() will encapsulate a brand new promise object p2. Since p2 is also a promise object, what are the status (promiseStatus) and value (promiseValue) of p2?

 

The rules are as follows:

If the status of p1 is pending, the status of p2 is also pending.

• If the state of p1 is resolved, then() will execute f_ok, and the state of p2 is determined by the return value of f_ok.

• If the return value of f_ok is not a promise object, the state of p2 is resolved, and the promiseValue of p2 is the return value of the f_ok function. • If the return value of f_ok is a promise object, the state and promiseValue of p2 are subject to this promise object. • If an error occurs inside the function f_ok (or the user actively throws an error), the status of p2 is rejected, and the promiseValue of p2 is the error object.

If the status of p1 is rejected, then() will execute f_err, and the status of p2 is determined by the return value of f_err.

• If the return value of f_err is not a promise object, the state of p2 is resolved, and the promiseValue of p2 is the return value of the f_err function. • If the return value of f_err is a promise object, the state and promiseValue of p2 are subject to this promise object.

• If an error occurs inside the function f_err (or the user actively throws an error), the status of p2 is rejected, and the promiseValue of p2 is the error object.

 

 

Sample code 1

The states of p1 and p2 are the same. ​​​​​​​

var p1 = new Promise(()=>{});var p2 = p1.then(function f_ok(){}, function f_err(){}); // p2也是一个promise对象。console.dir(p1);console.dir(p2);

Sample code 2

​​​​​​​

var p1 = new Promise((resolve,reject)=>{   resolve()});var p2 = p1.then(function f_ok(){
   
      return 1}, function f_err(){}); // p2也是一个promise对象。console.dir(p1);console.dir(p2);

 

The state and value of p2 are determined by f_ok. 

 

In particular, if there is no return statement in f_ok(), it is equivalent to return undefined.

Sample code 3

f_ok returns a brand new promise object, and the state and value of p2 are determined by this promise object. ​​​​​​​

var p1 = new Promise((resolve,reject)=>{ resolve()});var p2 = p1.then(function f_ok(){
   
       var temp = new Promise((resolve,reject)=>{ resolve({a:1}) });     return temp;}, function f_err(){});
console.dir(p2);

Sample code 4

An intentional error in f_ok() causes the status of p2 to be rejected, and the value is the error object. ​​​​​​​

var p1 = new Promise((resolve,reject)=>{ resolve()});var p2 = p1.then(function f_ok(){
   
       console.log(abc);// 这里故意犯错}, function f_err(){});
console.dir(p2);

Code Example 5

var p1 = new Promise((resolve,reject)=>{ reject(100)});var p2 = p1.then(function f_ok(){
   
   
}, function f_err(errVal){
   
     var temp = new Promise((resolve,reject)=>{     resolve({b:errVal})   });   return temp;});
console.dir(p2);

Code Example 6

var p1 = new Promise((resolve,reject)=>{ reject(100)});var p2 = p1.then(function f_ok(){
   
   
}, function f_err(errVal){
   
       throw new Error("aaa")}); console.dir(p2)

5 catch

5.1 The format and usage of catch()

Promise.prototype.catch is an alias of Promise.prototype.then(null, reject), used to specify the callback function when the state of the promise object changes from pending to rejected. ​​​​​​​

var p1 = new Promise((resolve,reject)=>{
   
       reject('s')});
p1.catch(function(err){
   
       console.log(err);})
// 与下面的代码等价p1.then(null, function(err){
   
       console.log(err);})

There is no point in using catch alone, it is generally used together with then. As follows:​​​​​​​

new Promise((resolve,reject)=>{
   
   
}).then(function(result){
   
       // 如果promise对象的状态是resolved的,就会到这里来,并且result会接收promiseValue的值}).catch(function(err){
   
       // 如果promise对象的状态是rejected的,就会到这里来,并且err会接收promiseValue的值})
// 上面的代码如何拆分来写的话,等价于:var p1 = new Promise((resolve,reject){
   
   
});var p2 = p1.then(function(result){
   
   
});var p3 = p2.catch(function(err){
   
   
})

5.2 The return value of catch

The return value of catch is still a promise object, and then(null,(errVal)=>{ })the method of determining its value is consistent with the method.

6 finally() method

Promise.prototype.finally(), regardless of whether the Promise status is resolved or rejected, the callback function will be executed (if the status is pending, it will not be executed). Its return value is still a promise, and retains the state and value of the original promise object. ​​​​​​​

var p1 = new Promise((resolve,reject)=>{ resolve(100)})var p2 = p1.finally(()=>{console.log('finally')})console.log(p1);console.log(p2);console.log(p1 === p2)

Note: (1) Its callback function is not executed, no matter whether it promiseis fulfilled or rejected, it will be executed. (2) The state that finallydoes not change promise.

7 Promise chain call

Since the return values ​​of the then and catch methods are promise objects, they can naturally be called in a chain. Let's analyze the execution logic of chain call through several questions.

7.1 Example 1​​​​​​​

function do1() {
   
       console.log("任务1");}function do2() {
   
       console.log("任务2");}function do3() {
   
        console.log("任务3");}function do4() {
   
       console.log("任务4");}
var p = new Promise((resolve,reject)=>{ resolve()})p.then(do1) .then(do2) .then(do3) .then(do4);

The output is the result:任务1,任务2,任务3,任务4

var p1 = p.then(do1);var p2 = p1.then(do2)var p3 = p2.then(do3)var p4 = p3.then(do4)

Step 1: Since the state of p is resolved, in p.then(do1), the do1 function will be executed. Output 任务1.

Step 2: Determine the state of p1. According to the introduction in the section about then, the state of p1 is determined by do1(). Because do1 does not explicitly specify the return value, the return value is undefined. The state of p1 is resolved.

Step 3: Since the state of p1 is resolved, p1.then(do2) will continue to execute do2. Output 任务2 , and the state of p2 is determined by do2. Same as the analysis in the second step, the status of p2 is still resolved.

Step 4: Next look at p3. Since the state of p2 is resolved, p2.then(do3) will continue to execute do3. Output 任务2 , and the state of p3 is determined by do3, and it is still resolved.

Finally: p3.then(do4). Since the status of p3 is resolved, do4 is executed. Output 任务4 .

7.2 Example 2​​​​​​​

function do1() {
   
       console.log("任务1");}function do2() {
   
       console.log("任务2");}function do3() {
   
        console.log("任务3");}function do4() {
   
       console.log("任务4");}
var p = new Promise((resolve,reject)=>{ resolve()})p.then(do1) .then(do2) .catch(do3) .then(do4);

Results of the above code is: 任务1, 任务2, 任务4. Let's break down the process first and add a few more intermediate variables to describe their values:​​​​​​​

var p1 = p.then(do1);var p2 = p1.then(do2)var p3 = p2.catch(do3)var p4 = p3.then(do4)

analyse as below:

Step 1: Since the state of p is resolved, in p.then(do1), the do1 function will be executed. Output 任务1.

Step 2: Determine the state of p1. According to the introduction in the section about then, the state of p1 is determined by do1(). Because do1 does not explicitly specify the return value, the return value is undefined. The state of p1 is resolved.

Step 3: Since the state of p1 is resolved, p1.then(do2) will continue to execute do2. Output 任务2 , and the state of p2 is determined by do2. Same as the analysis in the second step, the status of p2 is still resolved.

Step 4: Next look at p3. Since the state of p2 is resolved, it will not execute do3, the state of p3 has not changed, and the state of p2: resolved.

Finally: p3.then(do4). Since the status of p3 is resolved, do4 is executed. Output 任务4 .

7.3 Example 3​​​​​​​

function do1() {
   
       console.log("任务1");    console.log(abc); //故意犯错}function do2() {
   
       console.log("任务2");}function do3() {
   
        console.log("任务3");}function do4() {
   
       console.log("任务4");}
var p = new Promise((resolve,reject)=>{ resolve()})p.then(do1) .then(do2) .then(do3) .catch(do4);

Results of the above code is: 任务1, 任务4. Let's break down the process first and add a few more intermediate variables to describe their values:​​​​​​​

var p1 = p.then(do1)var p2 = p1.then(do2)var p3 = p2.then(do3)var p4 = p3.catch(do4)

analyse as below:

Step 1: Since the state of p is resolved, in p.then(do1), the do1 function will be executed and output 任务1. At the same time, because there is a segment error code, the state of p1 is rejected.

Step 2: Since the status of p1 is rejected, p1.then(do2) will not execute do2, and the status of p2 is also rejected.

Step 3: The same is true for the analysis of p3.

Step 4: The status of p3 is rejected, so do4 will be executed.

7.4 Example 4 Passing Parameters​​​​​​​

function increment(value) {
   
       return value + 1;}function doubleUp(value) {
   
       return value * 2;}function output(value) {
   
       console.log(value);// => (1 + 1) * 2}var p = Promise.resolve(1);p.then(increment) .then(doubleUp) .then(output)

The output of the above code is 4.

After the split, the analysis is as follows:​​​​​​​

// 状态:resolved; promiseValue: 1var p = Promise.resolve(1); 
// p的状态是resolved; // 在执行then的第一个参数,即increment时// 把p的 promiseValue 1 传入// increment执行后的返回值就是2// p1的状态是resolved,promiseValue是2 var p1 = p.then(increment); 
// p1的状态是resolved; // 在执行then的第一个参数,即doubleUp时// 把p1的promiseValue 2传入// doubleUp执行后的返回值就是4// p2的状态是resolved,promiseValue是4var p2 = p1.then(doubleUp); 
// p2的状态是resolved,promiseValue是4// 在执行then的第一个参数,即output时// 把p2的promiseValue传入,就是4var p3 = p2.then(output) ;

8 Summary

This article introduces the three prototype methods of the promise object, focusing on the parameter execution logic and return value of the then method, and finally analyzes the execution steps of the chain usage of the promise object. Hope it helps you.

Guess you like

Origin blog.csdn.net/sqLeiQ/article/details/110626335