手写Promise

100 阅读4分钟

Promise的特点

  • 三个状态: Pending fulfilled rejected
  • 状态不可逆,状态一旦改变,不可更改
  • resolve 调用之后 状态改为 fulfilled
  • reject 地啊欧之后 状态改为 rejected
  • then回调
    • 能接收两个回调, resolve, reject
    • then会在resolve或reject结果出来后执行
    • 可进行多次then 下次会受到上次的结果影响
    • then会返回一个Promise对象
    • then返回的不是Promise对象的时候,直接返回当前的值, 并且代表执行成功
var p1 = new Promise((resolve,reject) => {
    resolve('success')
    reject('fail')
})

console.log('p1', p1) 

首先实现第一个例子的Promise

// 创建一个类
class MyPromise { // 构造函数
    // 通过construator接收执行函数
    construator(exector) {
        // 初始化Promise的值
        this.initValue()
        // 因为例子中是使用new创建的Promise 调用的时候使用P1这个实例对象
        // 但是在构造函数中当前的this指向的是构造函数,所以通过bind把this指向实例对象
        this.initBind()
       try{
             // 执行exector内的函数
            exector(this.resolve, this.reject)
        } catch(e){
            this.reject(e)
        }
       
    }
    
    initValue(){
      // 初始化的时候状态为pending
      this.promiseStaus = 'pending'
      // 初始化的时候result没值
      this.promiseResult = null
    }
    
    initBind(){
     this.resolve = this.resolve.bind(this)
     this.reject = this.reject.bind(this)
    }
    
    // 实现resolve方法
    resolve(value){
       // 因为Promise有状态不可逆的特点 所以需要校验当前状态
       if(this.promiseStaus !== 'pending') return 
       // 成功状态为fulfilled
      this.promiseStaus = 'fulfilled'
      // 接收成功的value
      this.promiseResult = value
    }
    
    // 实现reject方法
    reject(reason){
    // 因为Promise有状态不可逆的特点 所以需要校验当前状态
       if(this.promiseStaus !== 'pending') return 
       // 失败状态为rejected
      this.promiseStaus = 'rejected'
      // 接收失败的reason
      this.promiseResult = reason
    }
}

带then处理的Promise

var p2 = new Promise((resolve,reject) => {
    resolve(100)
    reject('fail')
}).then(res=> console.log(res * 2)).catch(e => console.log(e))

console.log('p2', p2)  // Promise  200
// 创建一个类
class MyPromise { // 构造函数
    // 通过construator接收执行函数
    construator(exector) {
        // 初始化Promise的值
        this.initValue()
        // 因为例子中是使用new创建的Promise 调用的时候使用P1这个实例对象
        // 但是在构造函数中当前的this指向的是构造函数,所以通过bind把this指向实例对象
        this.initBind()
       try{
             // 执行exector内的函数
            exector(this.resolve, this.reject)
        } catch(e){
            this.reject(e)
        }
       
    }
    
    initValue(){
      // 初始化的时候状态为pending
      this.promiseStaus = 'pending'
      // 初始化的时候result没值
      this.promiseResult = null
    }
    
    initBind(){
     this.resolve = this.resolve.bind(this)
     this.reject = this.reject.bind(this)
    }
    
    // 实现resolve方法
    resolve(value){
    // 因为Promise有状态不可逆的特点 所以需要校验当前状态
       if(this.promiseStaus !== 'pending') return 
       // 成功状态为fulfilled
      this.promiseStaus = 'fulfilled'
      // 接收成功的value
      this.promiseResult = value
    }
    
    // 实现reject方法
    reject(reason){
    // 因为Promise有状态不可逆的特点 所以需要校验当前状态
       if(this.promiseStaus !== 'pending') return 
       // 失败状态为rejected
      this.promiseStaus = 'rejected'
      // 接收失败的reason
      this.promiseResult = reason
    }
    
    // 实现then
    then(onFulfilled, onRejected) {
        // 先校验这两个是不是函数
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : res => res
        onRejected = typeof onRejected === 'function' ? onRejected : reason => reason
        
        // 判断当前是什么状态执行什么函数
        if(this.promiseStaus === 'fulfilled') {
            onFulfilled(this.promiseResult)
        } else if(this.promiseStaus === 'rejected') {
            onRejected(this.promiseResult)
        }
    }
}

延迟后执行then

let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('success')
    }, 1000)
}).then(res => conosole.log(res))  // 1秒后打印success

实现这种可以延迟执行的promise

class MyPromise {
    construator(exector) {
        this.initValue()
        this.initBind()
        try{
            exector(this.resolve, this.reject)
        }.catch(e) {
            throw new Error(e)
        }
        // 创建两个存储调用方法的数组
        this.onFulfillmentCallbacks = []
        this.onRejectedCallbacks = []
    }
    
    initValue(){
        this.PromiseStaus = 'pending'
        this.PromiseResult = null
    }
    
    initBind(){
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    
    resolve(value) {
    // 因为Promise有状态不可逆的特点 所以需要校验当前状态
       if(this.promiseStaus !== 'pending') return 
        this.PromiseStaus = 'fulfilled'
        this.PromiseResult = value
        
        while(this.onFulfillmentCallbacks.length) {
             this.onFulfillmentCallbacks.shift()(this.PromiseResult)
        }
    }
    
    reject(reason) {
    // 因为Promise有状态不可逆的特点 所以需要校验当前状态
       if(this.promiseStaus !== 'pending') return 
        this.PromiseStaus = 'rejected'
        this.PromiseResult = reason
        
        while(this.onRejectedCallbacks.length) {
             this.onRejectedCallbacks.shift()(this.PromiseResult)
        }
    }
    
    then(onFulfilled, onRejected) {
     onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : res =>res
     onRejected = typeof onRejected === 'function' ? onRejected : err =>err
     
     if(this.PromiseStaus === 'fulfilled') {
         onFulfilled(this.PromiseResult)
     } else  if(this.PromiseStaus === 'rejected') {
         onRejected(this.PromiseResult)
     } else {
         // pending状态 存储调用方法
         this.onFulfillmentCallbacks.push(onFulfilled.bind(this))
         this.onRejectedCallbacks.push(onRejected.bind(this))
     }
    }
}

多次then处理

    let p1 = new Promise((resolve, reject) => {
        resolve(100)
    }),then(res => res * 3).then(data => console.log(data)) // 300

实现多次then调用

class MyPromise {
    construator(exector) {
        this.initValue()
        this.initBind()
        try{
            exector(this.resolve, this.reject)
        }.catch(e) {
            throw new Error(e)
        }
        // 创建两个存储调用方法的数组
        this.onFulfillmentCallbacks = []
        this.onRejectedCallbacks = []
    }
    
    initValue(){
        this.PromiseStaus = 'pending'
        this.PromiseResult = null
    }
    
    initBind(){
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    
    resolve(value) {
    // 因为Promise有状态不可逆的特点 所以需要校验当前状态
       if(this.promiseStaus !== 'pending') return 
        this.PromiseStaus = 'fulfilled'
        this.PromiseResult = value
        
        while(this.onFulfillmentCallbacks.length) {
             this.onFulfillmentCallbacks.shift()(this.PromiseResult)
        }
    }
    
    reject(reason) {
    // 因为Promise有状态不可逆的特点 所以需要校验当前状态
       if(this.promiseStaus !== 'pending') return 
        this.PromiseStaus = 'rejected'
        this.PromiseResult = reason
        
        while(this.onRejectedCallbacks.length) {
             this.onRejectedCallbacks.shift()(this.PromiseResult)
        }
    }
    
    then(onFulfilled, onRejected) {
     onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : res =>res
     onRejected = typeof onRejected === 'function' ? onRejected : err =>err
     let thenPromise = new MyPromise((resolve,reject) => {
         let resolvePromise = cb => {
            let x = cb(this.PromiseResult)
            
            // 判断当前x返回的不是thenPromise
            if(x && x === thenPromise) {
                throw new Error('不能返回自己')
            }
            
            try{
              // x是promise的实例的时候才可以进行调用then
              // 1.如果返回值是promise
              // 2.返回的值是promise对象,返回失败,新的promise对象是失败
              // 3.返回的值是promise对象,返回成功,新的promise对象是成功
                 if(x instanceof MyPromise) {
                     x.then(resolve,reject)
                 } else {
                     reject(x)
                 }
               } catch(e) {
                    reject(e)
                    throw new Error(e)
               }
         }
     })
     
     return thenPromise
     if(this.PromiseStaus === 'fulfilled') {
         onFulfilled(this.PromiseResult)
     } else  if(this.PromiseStaus === 'rejected') {
         onRejected(this.PromiseResult)
     } else {
         // pending状态 存储调用方法
         this.onFulfillmentCallbacks.push(onFulfilled.bind(this))
         this.onRejectedCallbacks.push(onRejected.bind(this))
     }
    }
}