[front end] learn Promise thoroughly

Posted by maryp on Thu, 13 Jan 2022 03:43:23 +0100

Author: D827

Source: Hang Seng LIGHT cloud community

None of the functions will not be used after reading the source code. So after reading this article, I hope it can help you completely master Promise.

Promise introduction

Promise object is a solution to realize asynchrony provided by ES6. It enables asynchronous methods to return values like synchronous methods.

promise is a constructor that wraps (encapsulates) an asynchronous function (ajax; timer; database read; fs file read). Of course, it can also wrap a non asynchronous function. The input parameters are two functions: resolve and reject. Resolve is called successfully and parameters are passed. Reject is called and parameters are passed in case of failure. use. then is used as the callback result. then accepts two function parameters. The first parameter accepts the correct return result, and the second function receives the wrong return result.

Promise has three statuses: pending, fullfilled/resolved, and rejected

The initial state of Promise is pending, and the state is modified to fullfilled/resolved through the resolve method; Change the status to rejected by reject

promise's advantages: it can realize chain call and solve the callback hell caused by asynchronous callback.

Disadvantages of promise:

  1. Unable to monitor the status of progress, execute the new immediately, and cannot cancel;
  2. If the callback function is not set, the error thrown by Promise will not be reflected to the outside;
  3. Sometimes it will cause multiple then chain calls, which may cause the semantics of the code to be unclear.

Basic use of Promise

function sleep(data){
    return new Promise((resolve,reject)=>{
    // The new Promise package can be an asynchronous code or a synchronous code
    // Code execution succeeded
        setTimeOut(()=>{
               let result = null
            if(1){
              resolve(result)  
            }else{
               reject(result) 
            } 
        },1000)
})
}
sleep(1000).then(v=>{
    // Correct return processing
},e=>{
   // Error return processing
}).then(v=>{
  
}).then(v=>{
  
})
......
.catch(e=>{
    // error handling
})

Problems needing attention and solutions for customizing Promise

  1. promise how to modify the status

    Modify the status by calling resolve and reject

  2. Can the status be modified by calling resolve and reject multiple times

    No, it cannot be changed to another state after changing from pending to resolved or rejected

  3. Whether promise modifies the status first or displays the execution then, and when to get the data

    Both situations may occur. When the content of promise package is asynchronous, specify then and then modify the state. On the contrary, modify the state first and then execute then;

    The data is obtained after the callback is executed.

  4. promise.then returns a promise. Who decides the returned type result

    The returned is promise, which is determined by the returned promise

    If the return is non promise, it is resolved

  5. How promise concatenates multiple operation tasks

    Because Promise Then returns a new Promise object, so you can also call then to implement the chain call

  6. promise exception penetration

    It means that no matter how many then there are, any one of them will be caught by the catch if an error is reported

  7. How to terminate promise chain

    Any one of then is abnormal;

    Change the state of promise to pending in any then.

Promise customization

 //Declaration constructor
 function Promise(executor){
     //Add attribute
     this.PromiseState = 'pending';
     this.PromiseResult = null;
     //There are multiple cases of declaring property callbacks
     this.callbacks = [];
     //Save the value of this of the instance object
     const self = this;// self _this that
     //resolve function
     function resolve(data){
         //Judge the status and call resolve and reject multiple times. The status cannot be modified
         if(self.PromiseState !== 'pending') return;
         //1. Modify the object's state (promiseState)
         self.PromiseState = 'fulfilled';// resolved
         //2. Set the object result value (promiseResult)
         self.PromiseResult = data;
         //Call successful callback function
         setTimeout(() => {
             self.callbacks.forEach(item => {
                 item.onResolved(data);
             });
         });
     }
     //reject function
     function reject(data){
         //Judgment state
         if(self.PromiseState !== 'pending') return;
         //1. Modify the object's state (promiseState)
         self.PromiseState = 'rejected';// 
         //2. Set the object result value (promiseResult)
         self.PromiseResult = data;
         //Failed callback execution
         setTimeout(() => {
             self.callbacks.forEach(item => {
                 item.onRejected(data);
             });
         });
     }
     try{
         //Synchronously call "actuator function"
         executor(resolve, reject);
     }catch(e){
         //Modify the promise object status to fail
         reject(e);
     }
 }
 
 //Add then method
 Promise.prototype.then = function(onResolved, onRejected){
     const self = this;
     //Determine callback function parameters
     if(typeof onRejected !== 'function'){
         onRejected = reason => {
             throw reason;
         }
     }
     if(typeof onResolved !== 'function'){
         onResolved = value => value;
         //value => { return value};
     }
     return new Promise((resolve, reject) => {
         //Encapsulation function
         function callback(type){
             try{
                 //Get the execution result of the callback function
                 let result = type(self.PromiseResult);
                 //judge
                 if(result instanceof Promise){
                     //If it is an object of Promise type
                     result.then(v => {
                         resolve(v);
                     }, r=>{
                         reject(r);
                     })
                 }else{
                     //The object status of the result is success
                     resolve(result);
                 }
             }catch(e){
                 reject(e);
             }
         }
         //Call the callback function PromiseState
         if(this.PromiseState === 'fulfilled'){
             setTimeout(() => {
                 callback(onResolved);
             });
         }
         if(this.PromiseState === 'rejected'){
             setTimeout(() => {
                 callback(onRejected);
             });
         }
         //Determine pending status
         if(this.PromiseState === 'pending'){
             // Save the callback function in asynchronous mode, and execute the callback function after asynchronous execution
             this.callbacks.push({
                 onResolved: function(){
                     callback(onResolved);
                 },
                 onRejected: function(){
                     callback(onRejected);
                 }
             });
         }
     })
 }
 
 //Add catch method
 Promise.prototype.catch = function(onRejected){
     return this.then(undefined, onRejected);
 }
 
 //Add resolve method
 Promise.resolve = function(value){
     //Return promise object
     return new Promise((resolve, reject) => {
         if(value instanceof Promise){
             value.then(v=>{
                 resolve(v);
             }, r=>{
                 reject(r);
             })
         }else{
             //The status is set to success
             resolve(value);
         }
     });
 }
 
 //Add reject method
 Promise.reject = function(reason){
     return new Promise((resolve, reject)=>{
         reject(reason);
     });
 }
 
 //Add all method
 Promise.all = function(promises){
     //The returned result is promise object
     return new Promise((resolve, reject) => {
         //Declare variable
         let count = 0;
         let arr = [];
         //ergodic
         for(let i=0;i<promises.length;i++){
             //
             promises[i].then(v => {
                 //Know that the status of the object is successful
                 //Each promise object succeeded
                 count++;
                 //Store the successful result of the current promise object into the array
                 arr[i] = v;
                 //judge
                 if(count === promises.length){
                     //modify state
                     resolve(arr);
                 }
             }, r => {
                 reject(r);
             });
         }
     });
 }
 
 //Add race method
 Promise.race = function(promises){
     return new Promise((resolve, reject) => {
         for(let i=0;i<promises.length;i++){
             promises[i].then(v => {
                 //Modify the status of the returned object to success
                 resolve(v);
             },r=>{
                 //Modify the status of the returned object to "failed"
                 reject(r);
             })
         }
     });
 }

I hope the above content is helpful to you!

Want to learn more from technology bosses? Where to discuss the problems encountered in development? How to obtain massive financial technology resources?

Hang Seng LIGHT cloud community , the financial technology professional community platform built by Hang Seng electronics shares practical technology dry goods, resource data and financial technology industry trends, and embraces all financial developers.

Scan the QR code of the applet below and join us!

Topics: Javascript Front-end Promise