手写Promise.resolve,Promise.reject, Promise.all

本文详细解读了Promise/A+规范,介绍了Promise的三种基本状态(pending、fulfilled、rejected)及其不变性,以及Promise构造函数的工作原理,重点讲解了then方法的实现策略和链式调用的处理。
摘要由CSDN通过智能技术生成
// // // promise/A+规范中说明promise有三种状态,且状态一旦被改变就不能再次发生变化
const PENDING = 'Pending'
const FULFILLED = 'Fulfilled'
const REJECTED = 'Rejected'
class Promise {
  // 高阶函数,函数的参数是函数,高阶函数可以实现参数的预置
  // 函数的参数中的函数为函数的声明
  // executor是立即执行的函数,参数被预置在了constructor中
  constructor(executor) {
    this.state = PENDING
    this.value = undefined         // 成功的结果
    this.reason = undefined        // 失败的理由
    
    // 解决then可以多次调用的问题
    this.onResolvedCallbacks = []   
    this.onRejectedCallbacks = []

    const resolve = (value) => {
      if(this.state === PENDING) {
        this.state = FULFILLED
        this.value = value
        // 当状态变化时再执行回调函数
        this.onResolvedCallbacks.forEach(cb => cb(value))
      }
    }

    const reject = (reason) => {
      if(this.state === PENDING) {
        this.state = REJECTED
        this.reason = reason
        // 当状态变化时再执行回调函数
        this.onRejectedCallbacks.forEach(cb => cb(reason))
      }
    }
   
    // 此处为executor函数的调用。参数传入resolve和reject两个函数
    try {
      executor(resolve, reject)
    } catch(err) {
      reject(err)
    }
  }
  then(onFulfilledCallback, onRejectedCallback) {
    onFulfilledCallback = typeof onFulfilledCallback === 'function' ? onFulfilledCallback : value => value
    onRejectedCallback = typeof onRejectedCallback === 'function' ? onRejectedCallback : reason => { throw reason } 

    // 可以链式调用,则then返回的必须是一个Promise
    let promise = new Promise((resolve, reject) => {
      if(this.state === FULFILLED) {
        // 优化捕捉异常
        setTimeout(() => {
          try {
            let res = onFulfilledCallback(this.value)
            // 根据res的不同类型做不同的处理
            resolvePromise(promise, res, resolve, reject)
          } catch(e) {
            reject(e)
          }
        })
      }
      
      if(this.state === REJECTED) {
        setTimeout(() => {
          try {
            let res = onRejectedCallback(this.reason)
            resolvePromise(promise, res, resolve, reject)
          } catch(e) {
            reject(e)
          }
        })
      }
      
      // 当executor出现异步任务时,then执行的时候,状态还未发生变化,可以将回调放到回调函数数组中
      if(this.state === PENDING) {
        this.onResolvedCallbacks.push((value) => {
          setTimeout(() => {
            try {
              let res = onFulfilledCallback(value)
              resolvePromise(promise, res, resolve, reject)
            } catch(e) {
              reject(e)
            }
          })
        }) 
        this.onRejectedCallbacks.push((reason) => {
          setTimeout(() => {
            try {
              let res = onRejectedCallback(reason)
              resolvePromise(promise, res, resolve, reject)
            } catch(e) {
              reject(e)
            }
          })
        })   
      }
    })
    return promise
  }
  static resolve(value) {
    if(value instanceof Promise) {
      return value
    } else {
      return new Promise((resolve, reject) => {
        resolve(value)
      })
    }
  }
  static reject(reason) {
    if(reason instanceof Promise) {
      return reason
    } else {
      return new Promise((resolve, reject) => {
        reject(reason)
      })
    }
  }
  catch(onRejectedCallback) {
    this.then(null, onRejectedCallback)
  }
  static all(args) {
    let results = []
    let i = 0 // 正确结果数量
    let iteratorIndex = -1 // 遍历索引,初始值为-1,遍历时从0开始

    return new Promise((resolve, reject) => {
      for (const item of args) {
        iteratorIndex += 1
        Promise.resolve(item).then(res => {
          results[iteratorIndex] = res
          i++
          if(i === (iteratorIndex + 1)) {
            resolve(results)
          }
        }).catch(err => {
          reject(err)
        })
      }
    })
  }
}

function resolvePromise(promise, res, resolve, reject) {
  if(res === promise) {
    return reject(new TypeError('死循环'))
  }

  if(res instanceof Promise) {
    try {
       res.then(x => {
         resolvePromise(promise, x, resolve, reject)
         // resolve(x)
       })
     } catch(e) {
       reject(e)
     }
  } else {
    resolve(res)
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值