史上最全,最用容易理解的promiseA+代码实现

91 阅读1分钟
class PstPromise {
  constructor(executor) {
    //promise的初始状态
    this.promiseState = "pending"
    this.resolveValue = null
    this.rejectValue = null
    //收集成功回调
    this.onFulfilledQueue = []
    //收集失败回调
    this.onRejectedQueue = []
    let resolve = (value) => {
      
      if (this.promiseState === "pending") {
        if (this.promiseState !== "pending") return
        //加入微任务对列
        queueMicrotask(() => {
          
          this.promiseState = "fulfilled"
          this.resolveValue = value
          this.onFulfilledQueue.forEach((fn) => {
            fn(this.resolveValue)
          })
        })
      }
    }
    let reject = (value) => {
      
      if (this.promiseState == "pending") {
        if (this.promiseState !== "pending") return
        queueMicrotask(() => {
          this.promiseState = "rejected"
          this.rejectValue = value
          this.onRejectedQueue.forEach((fn) => {
            fn(this.rejectValue)
          })
        })
      }
    }
    try {
      executor(resolve, reject)
    } catch (e) {
      reject(e)
    }
  }
  then(onFulfilled, onRejected) {
    return new PstPromise((resolve, reject) => {
      onRejected = typeof onRejected === 'function' ? onRejected : (error) => { throw error};
      onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => {value}
      if (this.promiseState === "pending") {
        this.onFulfilledQueue.push(() => {
          
          try {
            const value = onFulfilled(this.resolveValue)
            if(value instanceof PstPromise){
              value.then(resolve,reject)
            }else{
              resolve(value)
            }
          } catch (error) {
            reject(error)
          }
        })

        this.onRejectedQueue.push(() => {
          
          try {
            const value = onRejected(this.rejectValue)
            if(value instanceof PstPromise){
              value.then(resolve,reject)
            }else{
              resolve(value)
            }
          } catch (error) {
            reject(error)
          }
        })
      }
      if (this.promiseState == "fulfilled" && onFulfilled) {
        
        try {
          const value = onFulfilled(this.resolveValue)
          if(value instanceof PstPromise){
            value.then(resolve,reject)
          }else{
            resolve(value)
          }
        } catch (error) {
          reject(error)
        }
      }
      if (this.promiseState == "rejected" && onRejected) {

        try {
          let value = onRejected(this.rejectValue)
          if(value instanceof PstPromise){
            value.then(resolve,reject)
          }else{
            resolve(value)
          }
        } catch (error) {
          reject(error)
        }
      }
    })
  }
  catch(onRejected){
    return this.then(undefined,onRejected)
  }
  finally(onFinally){
    return this.then(onFinally,onFinally)
  }
  //当有一个promise失败就暂停,返回一个失败的promise
  static all(promises){
    return new PstPromise((resolve,reject) => {
      const values = [];
      promises.forEach(promise => {
        promise.then(res => {
          values.push(res);
          if(values.length > promises.length){
            resolve(values)
          }

        },(err) => {
          reject(err)
        })
      })
    })
  }

  //无论所有的promise成功或者失败,都返回结果
  static allSettled(promises){
    return new PstPromise((resolve,reject) => {
      const results = [];
      promises.forEach(promise => {
        promise.then((res)=> {
          results.push({status:'fulfilled',value:res})
        },(err) => {
          results.push({status:'rejected',value:err})
        })
      })
    })
  }
  
  //只要多个promises之中有一个实例率先改变状态,返回的promise的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给race函数返回的promise的回调函数
  static race(promises){
    return new PstPromise((resolve,reject) => {
      promises.forEach(promise => {
        promise.then(res => {
          resolve(res)
        },err => {
          reject(err)
        })
      })
    })
  }

  static any(promises){
    return new PstPromise((resolve,reject) => {
      let errValues = [];
      promises.forEach(promise => {
        promise.then(res => {
          resolve(res)
        },err => {
          errValues.push(err)
          if(errValues.length > promises.length){
            reject(new AggregateError(errValues))
          }
        })
      })
    })
  }
}
// const promise = new PstPromise((resolve, reject) => {
//   setTimeout(() => {
//     resolve("hello")
//   }, 1000)
// })
// promise.then(
//   (value) => {
//     console.log(value)
//   }
// ).finally((res) => {
//   console.log(res,'finally')
// })
function request(url){
  return new PstPromise((resolve,reject)=>{
      setTimeout(() => {
        resolve(url)
      },2000)
  })
}
request('http://why').then((res)=>{
  return request(res+'.base.com')
}).then(res => {
  console.log(res)
})