This is the 7th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.

portal

From zero tear Promise, grasp the realization principle of Promise (1) the realization of the basic structure of the Promise from zero tear Promise, grasp the realization principle of Promise (2) the basic version of the Promise realization from zero tear Promise, Master the implementation principle of the Promise (3) callback hell is what from zero rip Promise, master the implementation principle of the Promise (4) then method chain call preliminary implementation from zero rip Promise, Grasp the implementation principle of the Promise (5) then method chain call advanced implementation from zero hand tear Promise, grasp the implementation principle of the Promise (6) then method callback why is asynchronous microtask

review

After a few introductions, our Promise now looks like this

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const resolvePromise = (promise, x, resolve, reject) = >{}class Promise{
  constructor(executor){

    this.state = PENDING
    this.value = undefined
    this.reason = undefined
    / / store onFulfilled
    this.onResolvedCallbacks = []
    / / store onRejected
    this.onRejectedCallbacks = []
    const resolve = (value) = > {
      if (this.state === PENDING) {
        this.value = value
        this.state = FULFILLED
        // The promise instance will call ondepressing after its state changes
        this.onResolvedCallbacks.forEach(fn= > fn())
      }
    }

    const reject = (reason) = > {
      if (this.state === PENDING) {
        this.reason = reason
        this.state = REJECTED
        // onRejected called after the promise instance state changes
        this.onRejectedCallbacks.forEach(fn= > fn())
      }
    }
    try {
      // An error in the execution of the executor function will cause the Promise to fail
      executor(resolve,reject)
    } catch (error) {
      reject(error)
    }
  }
  then(onFulfilled, onRejected){

    let promise = new Promise((resolve, reject) = > {
        
        switch(this.state){
          case FULFILLED:
              setTimeout(() = > {
                try{
                  let x = onFulfilled(this.value)
                  resolvePromise(promise, x, resolve, reject)
                } catch(e){
                  reject(e)
                }
              })   
              break
          case REJECTED:
              setTimeout(() = > {
                try{
                  let x = onRejected(this.reason)
                  resolvePromise(promise, x, resolve, reject)
                } catch(e){
                  reject(e)
                }
              })   
              break
          default:
            this.onResolvedCallbacks.push(() = > {
              setTimeout(() = > {
                try{
                  let x = onFulfilled(this.value)
                  resolvePromise(promise, x, resolve, reject)
                } catch(e){
                  reject(e)
                }
              })
            })
            this.onRejectedCallbacks.push(() = > {
              setTimeout(() = > {
                try{
                  let x = onRejected(this.reason)
                  resolvePromise(promise, x, resolve, reject)
                } catch(e){
                  reject(e)
                }
              })
            })
        }
      
    })
    return promise
  }
}
Copy the code

thenMethodresolvePromisemethods

  • The purpose of resolvePromise is to parse the return value of the then callback function to determine what state the THEN method should return.

    1. In the first place to judgexBase type data, or reference type, base type data directlyresolveThat is ok.
    1. If it is referential data, try to fetch itxOn thethenProperties (x.then) if an exception is reported while getting the attributereject
    1. judgethenIs it a function or not? If it’s a function then we say it’s a functionPromiseIf not, thenresolve
    1. ifxIs aPromise, and we call histhenMethod, and then inthenMethod to callresolveorrejectIf the call returns an errorreject
    1. This shows if the callback in the then function returnsPromiseThen the state of the return value of the then function is the same as that returned by the callbackPromiseStates are closely related.
/* promise => then promise x => then promise x => then promise x => then Reject */ of the promise that the then function returns
const resolvePromise = (promise, x, resolve, reject) = > {

  / / 1.
  if(x ! = =null && /^(object|function)$/.test(typeof x)){
    let then 
    Then attribute (' x.chen ') on 'x'. Reject 'if an exception is reported
    try{
      then = x.then
    }catch(e){
      reject(e)
    }
    //3. Determine if 'then' is a function. If it is a function, then it is' Promise ', if not 'resolve'
    if(typeof then === 'function') {// 4. If 'x' is a 'Promise', we call his' then 'method, then in the' then 'callback, we call' resolve 'or' reject ', and if the call returns an error, 'reject'
      try{
        then.call(x, (y) = > {
          resolvePromise(promise, y, resolve, reject)
        },(r) = > {
          reject(r)
        })
      }catch(e){
        reject(e)
      }
    }else{
      resolve(x)
    }
  }else{
    // Base type data directly resolve
    resolve(x)
  }
}
Copy the code
  • 6. Repeat recursive call for serial number 1 in the following pictureresolvePromiseTo prevent, for example, the following code from returning a multiple nested resultPromiseIn turn, you need to recurse.

let p = new Promise((resolve,reject) = > {
    resolve('success')
})

p.then(value= > {
  console.log('value',value);
  // The then successful callback returns a Promise, and its value is a Promise, nested multiple times.
  // So the recursive call to resolvePromise resolves this situation
  return new Promise((resolve,reject) = > { // The first promise
    resolve(
        // The second promise
        new Promise((resolve,reject) = > {
          resolve('success')}))})},reason= > {
  console.log('reason',reason);
}).then(value= > {
  console.log('value',value);
},reason= > {
  console.log('reason',reason);
})
Copy the code
  • The execution result

Print the result twice, correct. (Print the first time for P.teng and the second time for p.teng. Then)

So here’s ourPromiseThat long

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const resolvePromise = (promise, x, resolve, reject) = > {

  // 1. Determine whether 'x' is a base type or a reference type.
  if(x ! = =null && /^(object|function)$/.test(typeof x)){
    let then 
    Then attribute (' x.chen ') on 'x'. Reject 'if an exception is reported
    try{
      then = x.then
    }catch(e){
      reject(e)
    }
    //3. Determine if 'then' is a function. If it is a function, then it is' Promise ', if not 'resolve'
    if(typeof then === 'function') {//4. If 'x' is a 'Promise', we call his' then 'method, then in the' then 'callback, we call' resolve 'or' reject ', and if the call returns an error, 'reject'
      try{
        then.call(x, (y) = > {
          resolvePromise(promise, y, resolve, reject)
        },(r) = > {
          reject(r)
        })
      }catch(e){
        reject(e)
      }
    }else{
      resolve(x)
    }
  }else{
    // Base type data directly resolve
    resolve(x)
  }
}
class Promise{
  constructor(executor){

    this.state = PENDING
    this.value = undefined
    this.reason = undefined
    / / store onFulfilled
    this.onResolvedCallbacks = []
    / / store onRejected
    this.onRejectedCallbacks = []
    const resolve = (value) = > {
      if (this.state === PENDING) {
        this.value = value
        this.state = FULFILLED
        // The promise instance will call ondepressing after its state changes
        this.onResolvedCallbacks.forEach(fn= > fn())
      }
    }

    const reject = (reason) = > {
      if (this.state === PENDING) {
        this.reason = reason
        this.state = REJECTED
        // onRejected called after the promise instance state changes
        this.onRejectedCallbacks.forEach(fn= > fn())
      }
    }
    try {
      // An error in the execution of the executor function will cause the Promise to fail
      executor(resolve,reject)
    } catch (error) {
      reject(error)
    }
  }
  then(onFulfilled, onRejected){

    let promise = new Promise((resolve, reject) = > {
        
        switch(this.state){
          case FULFILLED:
              setTimeout(() = > {
                try{
                  let x = onFulfilled(this.value)
                  resolvePromise(promise, x, resolve, reject)
                } catch(e){
                  reject(e)
                }
              })   
              break
          case REJECTED:
              setTimeout(() = > {
                try{
                  let x = onRejected(this.reason)
                  resolvePromise(promise, x, resolve, reject)
                } catch(e){
                  reject(e)
                }
              })   
              break
          default:
            this.onResolvedCallbacks.push(() = > {
              setTimeout(() = > {
                try{
                  let x = onFulfilled(this.value)
                  resolvePromise(promise, x, resolve, reject)
                } catch(e){
                  reject(e)
                }
              })
            })
            this.onRejectedCallbacks.push(() = > {
              setTimeout(() = > {
                try{
                  let x = onRejected(this.reason)
                  resolvePromise(promise, x, resolve, reject)
                } catch(e){
                  reject(e)
                }
              })
            })
        }
      
    })
    return promise
  }
}

module.exports=Promise
Copy the code

At this point, ourthenMethod, there are some minor flaws, soon our Promise will be completed, the next article will continue to finish

portal

From zero tear Promise, grasp the realization principle of Promise (1) the realization of the basic structure of the Promise from zero tear Promise, grasp the realization principle of Promise (2) the basic version of the Promise realization from zero tear Promise, Master the implementation principle of the Promise (3) callback hell is what from zero rip Promise, master the implementation principle of the Promise (4) then method chain call preliminary implementation from zero rip Promise, Grasp the implementation principle of the Promise (5) then method chain call advanced implementation from zero hand tear Promise, grasp the implementation principle of the Promise (6) then method callback why is asynchronous microtask