This is the 9th day of my participation in the November Gwen Challenge. See details: The Last Gwen Challenge 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 rip Promise, grasp the implementation principle of the Promise (6) then method callback why is asynchronous microtask from zero rip Promise, Master the implementation principle of Promise (7)then method chain call core method resolvePromise from zero hand tear Promise, master the implementation principle of Promise (8)then method chain call core method resolvePromise again explore

review

After the introduction of the last few articles, we are now nearing the end of our Promise, and our Promsie now looks like this

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') {let called = false / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * added a variable here * * * * * * * * * * * * * * * * * * * * * * * * * / / / / / /
      try{
        then.call(x, (y) = > {
          if(called) return / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * added a variable here * * * * * * * * * * * * * * * * * * * * * * * * * / / / / / /
          called = true
          resolvePromise(promise, y, resolve, reject)
        },(r) = > {
          if(called) return/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * added a variable here * * * * * * * * * * * * * * * * * * * * * * * * * / / / / / /
          reject(r)
        })
      }catch(e){
        if(called) return/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * added a variable here * * * * * * * * * * * * * * * * * * * * * * * * * / / / / / /
        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
  }
}
Copy the code

The resolvePromise method resolves minor flaws

  • Let’s look at the following code, and say,thenReturn from the callback functionPromiseisthenReturned by the function itselfPromsie, there will be problems.
  • What could go wrong?
    • Following the execution logic of our code, first of allthenThe callback function returns onePromsie, byresolvePromsieMethod to parse.
    • Take the following codepThenIs the firstthenThe return value of the function, and thepThenAs thethenThe return value of the successful callback, thenresolvePromsieMethod is called againpThenthethenMethods,pThenThis instance is its ownresolvewithreject“, thus creating an endless cycle of waiting for their own state. (Like a ridiculous example, I wait for me to cook for myself, we will never wait)
let p = new Promise((resolve,reject) = > {
  resolve('success')})let pThen = then(value= > {
return pThen
}).then(value= > {
console.log('value',value);
},reason= > {
console.log('reason',reason);
})
Copy the code
  • So for this problem, we need to reinvent itresolvePromsieMethod, make a small judgment, the code is as follows
const resolvePromise = (promise, x, resolve, reject) = > {
  / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * to determine whether x and promsie the same promise, Prevent an infinite loop *********************//////*********
  if(x === promise) throw new TypeError('Chaining cycle detected for promise #<Promise>')


  // 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') {let called = false 
      try{
        then.call(x, (y) = > {
          if(called) return 
          called = true
          resolvePromise(promise, y, resolve, reject)
        },(r) = > {
          if(called) return
          reject(r)
        })
      }catch(e){
        if(called) return
        reject(e)
      }
    }else{
      resolve(x)
    }
  }else{
    // Base type data directly resolve
    resolve(x)
  }
}
Copy the code

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 rip Promise, grasp the implementation principle of the Promise (6) then method callback why is asynchronous microtask from zero rip Promise, Master the implementation principle of Promise (7)then method chain call core method resolvePromise from zero hand tear Promise, master the implementation principle of Promise (8)then method chain call core method resolvePromise again explore

The next article will solve itthenA flaw in the method