1. The target

Understand the basic implementation principles of promises and properly understand and use promises

2. Implement a simplified version of Promise

2.1 Understand the functionality of Promises

Look at the use of Promise

 const a = new Promise((resolve,reject) = > {});
  a.then(a= > {
        console.log('a',a)
  })
Copy the code
  1. Is a function that can be new (here using es6 calss)

  2. Accept a callback with two arguments, resolve,reject;

    Call resolve to customize the content you want to return, and state it from Pending –> Depressing

    Call Reject to customize the error cause returned from pending –> rejectd

  3. Executed immediately

  4. There are three states

    Status: PENDING depressing REJECTED

    State flow:

               pending ---> fulfilled 
    
               pending ---> rejected 
              
    Copy the code
  5. Instance methods

5.1 then

  • Instance method, not mounted on Prototype;

  • Ondepressing onRejected;

5.2 resole

Call resolve to customize the content you want to return, and state it from Pending –> Depressing

5.3 reject

Call Reject to customize the error cause returned from pending –> rejectd

2.2 Implementation of building the initial MPromise class

  • Structural class

  • Class attribute

    Value: a successful return value (undefined, thenable, promise) reason: Error return value Status: state resolve: the promise callback for the first parameter (the instance calls the fulfilled method with the fulfilled state) reject: the promise callback for the second parameter (the instance calls the fulfilled method with the fulfilled state)Copy the code
  • code

    
       const PENDING = 'PENDING';
       const REJECTED = 'REJECTED';
       const FULFILLED = 'FULFILLED';
    
       class MPromise{
         constructor(fn) {
           this.value = undefined;
           this.reason = undefined;
           this.status = PENDING;
         }
    
         resolve(newValue) {
             if(this.status === PENDING) { // State can only change from one state to another, irreversibly
               this.status = FULFILLED;
               this.value = newValue; }}reject(newReason) {
             if(this.status === 'PENDING') {
               this.status = REJECTED;
               this.reason = newReason; }}}const testP = new MPromise((resolve,reject) = >{});console.log('testP',testP); // The state is pending
    Copy the code

2.3 Implement immediate implementation of promises

Now the test uses promise, which, according to the PROMSI specification, would immediately print 000, but it doesn’t.

Q: How do I execute anonymous functions (resolve,reject) => {}?

A: Do this in the constructor class

    const testP = new MPromise((resolve,reject) = > {
      console.log('000')});Copy the code

Modify the implementation code:

    constructor(fn) {
         this.value = undefined;
         this.reason = undefined;
         this.status = PENDING;
         try {  // try to prevent errors
           fn(this.resolve.bind(this),this.reject.bind(this));
         } catch (error) {
             this.reject(error)
         }
       } 
Copy the code

Test execution:

         
    const testP = new MPromise((resolve,reject) = > {
       console.log('000')});console.log('testP',testP); // The state is pending
     
     const testP = new MPromise((resolve,reject) = > {
         console.log('000')
         resolve('ddd')});console.log('testP',testP); // This is a big pity
     
     const testP = new MPromise((resolve,reject) = > {
       console.log('000')
       reject('wrong')});console.log('testP',testP); // The status is rejectd
Copy the code

Conclusion:

  • New PROMISE If resolve is not executed, reject is always pending

  • Perform resolve, and the state is depressing

  • Run reject. The status is rejected

2.4 implementation then

When will it be implemented? (Execute when the state changes to a final state, after resolve,reject)

   
         then(onFulfilled,onRejected) { 
              if(this.status === 'FULFILLED') {
                onFulfilled(this.value);
              }
              if(this.status === 'REJECTED') {
                onRejected(this.reason); }}Copy the code

Test execution:

   const testP = new MPromise((resolve,reject) = > {
      console.log('000')
      resolve('dddd')});const testPthen= testP.then((a,b) = > {  // onRejected is not a function
      console.log(The '-',a); 
    });
Copy the code

If the onfunction ledonRejected is not a function, a default function will be executed

   isFun(fn) {
    return typeof fn === 'function';
   }
   then(onFulfilled,onRejected) {
     if(this.status === FULFILLED) {
       const isOnFulfilled = this.isFun(onFulfilled)? onFulfilled:(value) = > value;
       isOnFulfilled(this.value);
     }
     if(this.status === REJECTED) {
       const isOnRejected = this.isFun(onRejected)? onRejected:(reason) = > reason;
       isOnRejected(this.reason); }}Copy the code

Test execution:

    const testPthen= testP.then((ful,rej) = > {
         console.log('ful',ful);
         console.log('rej',rej);
       });
Copy the code

2.5 Processing Asynchronous Tasks

When executing an asynchronous function in a promise, execute resolve,reject in asynchrony because promsie’s return state is pending and then will not execute.

For example:

  const testP = new MPromise((resolve,reject) = > {
       setTimeout(() = > {
         console.log('111')
         resolve('This value')},1000)});console.log('testP',testP); // pending

   testP.then((ful) = > {  
     console.log('ful',ful) // undefined
   })
Copy the code

How to solve it?

  • Then, the state is pending, and the asynchronous task is placed in the corresponding queue.
  • Resolve or Reject this asynchronous queue task
  const PENDING = 'PENDING';
const REJECTED = 'REJECTED';
const FULFILLED = 'FULFILLED';

class MPromise{
 constructor(fn) {
   this.value = undefined;
   this.reason = undefined;
   this.status = PENDING;
   this.onFulfillListCallback = []; // Asynchronous storage
   this.onRejectedListCallback = []; // Asynchronous storage
   try {  // prevent errors
     fn(this.resolve.bind(this),this.reject.bind(this));   // Bind this to prevent this from being lost
   } catch (error) {
      this.reject(error); }}resolve(newValue) {
    if(this.status === PENDING) { // State can only change from one state to another, irreversibly
      this.status = FULFILLED;
      this.value = newValue;

      this.onFulfillListCallback.forEach(fn= >fn()); }}reject(newReason) {
    if(this.status === 'PENDING') {
      this.status = REJECTED;
      this.reason = newReason;

      this.onRejectedListCallback.forEach(fn= >fn()); }}isFun(fn) {
   return typeof fn === 'function';
 }
 then(onFulfilled,onRejected) {
  const isOnFulfilled = this.isFun(onFulfilled)? onFulfilled:(value) = > value;
  const isOnRejected = this.isFun(onRejected)? onRejected:(reason) = > reason;
    if(this.status === FULFILLED) {
      isOnFulfilled(this.value);
    }
    if(this.status === REJECTED) {
      isOnRejected(this.reason);
    }

    if(this.status === PENDING) {
      this.onFulfillListCallback.push(() = > {
        isOnFulfilled(this.value);

      });
      this.onRejectedListCallback.push(() = > {
        isOnRejected(this.reason); }); }}}Copy the code

Test code:

  const testP = new MPromise((resolve,reject) = > {
    setTimeout(() = > {
      console.log('111')
      resolve('This value')},1000)});console.log('testP',testP); // fulfilled

testP.then((ful) = > {
  console.log('ful',ful) / / this value
})
Copy the code

2.6 Then returns a promise

Temporary unrealized

3. State flow of various methods of Promise

Test code 1:

const PromiseA = new Promise((resolve,reject) = >{});console.log('PromiseA',PromiseA); // pending
Copy the code

Promise.all: promise.all([PromiseA,PromiseB]);

  • This is a big pity, all is a big pity
  • There is a rejected,all
  • Other cases are pending

Promise.race is whichever state is returned first

  • Both are pending. Race is pending
  • The first thing to return is fulfilled,race is fulfilled
  • The first return is Rejected,race is Rejected

Promise. Allsettled will wait until all the results are finished, and then return all the values, which is a pity, and there is no rejected state

  • There is a pending. Allsettled is pending
  • This is a big pity, when all the states will return (depressing or Rejected), Allsettled is a big pity

Promise.any

  • All pending, any is pending
  • A. rejected B. any C. rejected D. any
  • There is a big pity

Finally a method to execute without promsie state, only say without state

const PromiseA = new Promise((resolve,reject) = > {
  reject('fff') 
}).finally(() = > {});
Copy the code
  • Pending for