Skip to content
本页目录

Promise

更具体的实现,推荐查看ECMAScript源码中对应方法的实现,传送门Promise

状态定义

JavaScript
// 进行中
const PENDING = 'PENDING'
// 已成功
const FULFILLED = 'FULFILLED'
// 已失败
const REJECTED = 'REJECTED'

构造函数

JavaScript
class Promise {
  constructor(executor) {
    this.status = PENDING
    //  将成功、失败结果放在this上,便于then、catch访问
    this.value = undefined
    this.reason = undefined
    // 成功态回调函数队列
    this.onFulfilledCB = []
    // 失败态回调函数队列
    this.onRejectedCB = []

    const resolve = value => {
      // 只有 PENDING 状态才能修改状态
      if (this.status === PENDING) {
        this.status = FULFILLED
        this.value = value
        // 成功态函数依次执行
        this.onFulfilledCB.forEach(cb => cb(this.value))
      }
    }

    const reject = reason => {
      // 只有 PENDING 状态才能修改状态
      if (this.status === PENDING) {
        this.status = REJECTED
        this.reason = reason
        // 失败态函数依次执行
        this.onRejectedCB.forEach(cb => cb(this.reason))
      }
    }
    // 立即执行executor
    try {
      executor(resolve, reject)
    } catch (e) {
      reject(e)
    }
  }
}

Promise#then()方法

JavaScript
class Promise {
  // ...

  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw new Error(reason) }
    const self = this
    return new Promise((resolve, reject) => {
      const judge = (flag) => {
        try {
          // 模拟异步任务
          setTimeout(() => {
            const ret = flag ? onFulfilled(self.value) : onRejected(self.value)
            ret instanceof Promise ? ret.then(resolve, reject) : resolve(ret)
          })
        } catch (e) { reject(e) }
      }
      if (self.status === PENDING) {
        self.onFulfilledCB.push(() => judge(true))
        self.onRejectedCB.push(() => judge(false))
      } else if (self.status === FULFILLED) {
        judge(true)
      } else if (self.value === REJECTED) {
        judge(false)
      }
    })
  }
}

Promise#catch()方法

JavaScript
class Promise {
  // ...

  catch(onRejected) {
    return this.then(null, onRejected)
  }
}

Promise#finally()方法

JavaScript
class Promise {
  // ...

  finally(cb) {
    const C = this.constructor
    return this.then(
      value => C.resolve(cb()).then(() => value),
      reason => C.resolve(cb()).then(() => { throw new Error(reason) })
    )
  }
}

Promise.resolve()方法

JavaScript
class Promise {
  // ...

  static resolve(value) {
    if (value instanceof Promise) {
      // 是Promise实例,直接返回
      return value
    } else {
      // 不是,则返回一个新的Promise对象
      return new Promise((resolve, reject) => resolve(value))
    }
  }
}

Promise.reject()方法

JavaScript
class Promise {
  // ...

  static reject(reason) {
    return new Promise((resolve, reject) => reject(reason))
  }
}

Promise.race()方法

JavaScript
class Promise {
  // ...

  static race(eles) {
    return new Promise((resolve, reject) => {
      eles.forEach(ele => {
        Promise.resolve(ele).then(
          value => resolve(value), 
          reason => reject(reason))
      })
    })
  }
}

Promise.all()方法

JavaScript
class Promise {
  // ...

  static all(eles) {
    const len = eles.length
    const done = Array(len)
    let cnt = 0
    return new Promise((resolve, reject) => {
      for (const ele of eles) {
        Promise.resolve(ele).then(
          value => {
            done.push(value)
            cnt++
            if (cnt === len) resolve(done)
          },
          reason => reject(reason))
      }
    })
  }
}