“This is the 20th day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021”.

portal

Tear Promise from zero hand, master the realization of the Promise principle (1) of the basic structure of the Promise

From scratch tear Promise, grasp the Promise realization principle (2) of the basic version of the Promise

Tear Promise from scratch, Master Promise realization principle (3) Callback what is hell

From scratch tear Promise, master the Promise realization principle (4) then method chain call preliminary implementation

From scratch tear Promise, master the Promise realization principle (5) then method chain call of the advanced implementation

Why is the callback of then method asynchronous microtask

(7) Then the core method of chain call resolvePromise

(8) The core method of chain call of then method resolvePromise is explored again

(9) Then method chain call core method resolvePromise complete

Tear Promise from scratch, master the realization principle of Promise (10)then method to complete all

Test whether all promises comply with PromiseA+ by learning how to implement promises (11)

What? Promise.resolve() can also return a failed Promise (12)

From zero hand tear Promise, grasp the realization principle of Promise (13) hand tear Promise finally method

Tear Promise from zero, grasp the realization principle of Promise (14) the all method of tear Promise

review

After last time, our Promise completed the all method, and now Promsie looks like this.

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
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 / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 we find that value is a Promise, we need to call value's then method to recursively resolve it
      if(value instanceof Promise) {return value.then(resolve,reject); // recursive parsing
      }
      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){
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v= > v
    onRejected = typeof onRejected === 'function' ? onRejected : err= > { throw err }
    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
  }
  catch(onRejected){
    return this.then(null, onRejected)
  }

  finally(cb){
    return this.then(
        (y) = > {
        return Promise.resolve(cb()).then(() = > y)
        },
        (r) = > {
        return Promise.resolve(cb()).then(() = > {throw r})
        }
    )
  }  

  static rsolve(value){
    return new Promise((resolve,reject) = >{ resolve(value); })}static reject(reason){
      return new Promise((resolve,reject) = >{ reject(reason); })}static all (promsies){
        return new Promise((resolve, reject) = > {
            const arr = []

            let count = 0
            const processResult = (i, val) = > {
                arr[i] = val
                if(++times === promises.length) resolve(arr)
            }

            for(let i = 0; i < promises.length; i++){
                let val = promises[i]
                if(typeof val.then === 'function'){
                    val.then(y= > processResult(i, y), reject)
                }else{
                    processResult(i, val)
                }
            }
        })
    }

}
Copy the code

Promise.raceRealize the principle of

  • Promise.raceMethod is alsoPromiseThe static method of thePromiseThe array. Only withPromise.allIn a different way,Promise.allIs that all success is success, and one failure is failure.Promise.raceIs used to take the result of the fastest completed Promise as the final result.

Promise.race takes the results of the fastest Promsie as a result, but does not interrupt the execution of other promises, except that the other results are not taken, with no breaking effect. The characteristic of promsie. all is that all promsies succeed, one fails, and the other promsies are executed.

  • Principle of implementation
static race(promises) {
    return new Promsie((resolve, reject) = >{
        for(let i = 0; i < promise.length; i++){
            let p = promises[i]
            Promise.resolve(p).then(resolve, reject)
        }
    })
}

Copy the code

finishing

So far, our Promsie has completed resolve, Reject, catch, finally, All, and race, and now the Promise is relatively complete. After a little tidying up, the Promise now looks like this.

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
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 / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 we find that value is a Promise, we need to call value's then method to recursively resolve it
      if(value instanceof Promise) {return value.then(resolve,reject); // recursive parsing
      }
      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){
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v= > v
    onRejected = typeof onRejected === 'function' ? onRejected : err= > { throw err }
    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
  }
  catch(onRejected){
    return this.then(null, onRejected)
  }

  finally(cb){
    return this.then(
        (y) = > {
        return Promise.resolve(cb()).then(() = > y)
        },
        (r) = > {
        return Promise.resolve(cb()).then(() = > {throw r})
        }
    )
  }  

  static rsolve(value){
    return new Promise((resolve,reject) = >{ resolve(value); })}static reject(reason){
      return new Promise((resolve,reject) = >{ reject(reason); })}static all (promsies){
        return new Promise((resolve, reject) = > {
            const arr = []

            let count = 0
            const processResult = (i, val) = > {
                arr[i] = val
                if(++times === promises.length) resolve(arr)
            }

            for(let i = 0; i < promises.length; i++){
                let val = promises[i]
                if(typeof val.then === 'function'){
                    val.then(y= > processResult(i, y), reject)
                }else{
                    processResult(i, val)
                }
            }
        })
  }
  static race(promises) {
        return new Promsie((resolve, reject) = >{
            for(let i = 0; i < promise.length; i++){
                let p = promises[i]
                Promise.resolve(p).then(resolve, reject)
            }
        })
  }

}
Copy the code

portal

Tear Promise from zero hand, master the realization of the Promise principle (1) of the basic structure of the Promise

From scratch tear Promise, grasp the Promise realization principle (2) of the basic version of the Promise

Tear Promise from scratch, Master Promise realization principle (3) Callback what is hell

From scratch tear Promise, master the Promise realization principle (4) then method chain call preliminary implementation

From scratch tear Promise, master the Promise realization principle (5) then method chain call of the advanced implementation

Why is the callback of then method asynchronous microtask

(7) Then the core method of chain call resolvePromise

(8) The core method of chain call of then method resolvePromise is explored again

(9) Then method chain call core method resolvePromise complete

Tear Promise from scratch, master the realization principle of Promise (10)then method to complete all

Test whether all promises comply with PromiseA+ by learning how to implement promises (11)

What? Promise.resolve() can also return a failed Promise (12)

From zero hand tear Promise, grasp the realization principle of Promise (13) hand tear Promise finally method

Tear Promise from zero, grasp the realization principle of Promise (14) the all method of tear Promise