真正手把手教你写一个自己的 Promise

1,071 阅读10分钟

介绍

在本文中,将会通过测试先行的方式来教你创建一个 Promise

正文

为了更好的梳理思路,可以采用测试先行的方式来实现 Promise,这里我使用jest作为功能测试框架

带有注释的是每一步新增的代码

3.1 constructor

1. 应该立刻执行构造函数传入的代码

Test Case

test('应该立刻执行构造函数传入的代码', () => {
  let timer = 0
  new _Promise(() => {
    timer++
  })
  expect(timer).toBe(1)
})

Code

class _Promise {
  constructor(executor) {
    executor()
  }
}

2. promise 有 3 种状态

Test Case

test('promise 有 3 种状态', () => {
  const p1 = new _Promise()
  expect(p1.status).toBe('pending')
  const p2 = new _Promise(resolve => resolve())
  expect(p2.status).toBe('fulfilled')
  const p3 = new _Promise((resolve, reject) => reject())
  expect(p3.status).toBe('rejected')
})

Code

// 新增 3 种状态
const STATUS_PENDING = 'pending'
const STATUS_FULFILLED = 'fulfilled'
const STATUS_REJECTED = 'rejected'

class _Promise {
  constructor(executor = () => {}) {
    // 立即执行构造函数,并且状态变为 pending
    this.status = STATUS_PENDING
    const resolve = () => {
      // 执行 resolve 后,状态变为 fulfilled
      this.status = STATUS_FULFILLED
    }
    const reject = () => {
      // 执行 reject 后,状态变为 rejected
      this.status = STATUS_REJECTED
    }
    // 传入的回调会有两个参数 resolve/reject
    executor(resolve, reject)
  }
}

3. 执行 resolve、reject 后状态固化

Test Case

test('执行 resolve、reject 后状态固化 ', () => {
  const p1 = new _Promise((resolve, reject) => {
    resolve()
    reject()
  })
  expect(p1.status).toBe('fulfilled')
  const p2 = new _Promise((resolve, reject) => {
    reject()
    resolve()
  })
  expect(p2.status).toBe('rejected')
})

Code

const STATUS_PENDING = 'pending'
const STATUS_FULFILLED = 'fulfilled'
const STATUS_REJECTED = 'rejected'

export class _Promise {
  constructor(executor = () => {}) {
    this.status = STATUS_PENDING
    const resolve = () => {
      // 如果状态时 PENDING 时才会执行代码
      if (this.status === STATUS_PENDING) {
        this.status = STATUS_FULFILLED
      }
    }
    const reject = () => {
      // 如果状态时 PENDING 时才会执行代码
      if (this.status === STATUS_PENDING) {
        this.status = STATUS_REJECTED
      }
    }
    executor(resolve, reject)
  }
}

3.2 then

1. then 方法可以接收两个参数,可以处理 resolve 和 reject

Test Case

test('then 方法可以接收两个参数,可以处理 resolve 和 reject', () => {
  new _Promise(resolve => {
    resolve('success')
  }).then(res => {
    expect(res).toBe('success')
  })
  new _Promise((resolve, reject) => {
    reject('error')
  }).then(undefined, err => {
    expect(err).toBe('error')
  })
})

Code

const STATUS_PENDING = 'pending'
const STATUS_FULFILLED = 'fulfilled'
const STATUS_REJECTED = 'rejected'

export class _Promise {
  constructor(executor = () => {}) {
    this.status = STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    // resolve 需要接收一个参数
    const resolve = value => {
      if (this.status === STATUS_PENDING) {
        this.status = STATUS_FULFILLED
        // 将接收的参数保存在 Promise 种
        this.value = value
      }
    }
    // reject 也可以接收一个参数
    const reject = reason => {
      if (this.status === STATUS_PENDING) {
        this.status = STATUS_REJECTED
        this.reason = reason
      }
    }
    executor(resolve, reject)
  }
  // 实例方法 then
  then(onFulfilled, onRejected) {
    if (onFulfilled) onFulfilled(this.value)
    if (onRejected) onRejected(this.reason)
  }
}

2. executor 可以是一个异步函数

Test Case

test('executor 可以是一个异步函数', () => {
  new _Promise(resolve => {
    setTimeout(() => {
      resolve('success')
    }, 300)
  }).then(res => {
    expect(res).toBe('success')
  })
  new _Promise((resolve, reject) => {
    setTimeout(() => {
      reject('error')
    }, 300)
  }).then(undefined, err => {
    expect(err).toBe('error')
  })
})

Code

class _Promise {
  constructor(executor = () => {}) {
    this.status = STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    // 因为可以执行多次 then,因此需要将所有的任务放在一个队列中
    this.resolveQueue = []
    this.rejectQueue = []
    const resolve = value => {
      if (this.status === STATUS_PENDING) {
        this.status = STATUS_FULFILLED
        this.value = value
        // 在 resolve 时执行 resolveQueue 所有的任务
        if (this.resolveQueue.length)
          this.resolveQueue.forEach(item => item(this.value))
      }
    }
    const reject = reason => {
      if (this.status === STATUS_PENDING) {
        this.status = STATUS_REJECTED
        this.reason = reason
        // 在 reject 时执行 rejectQueue 所有的任务
        if (this.rejectQueue.length)
          this.rejectQueue.forEach(item => item(this.reason))
      }
    }
    executor(resolve, reject)
  }
  then(onFulfilled, onRejected) {
    // 由于 executor 可能是一个异步函数,所以就不能直接来执行
    // 传入的参数了,需要做一下状态判断
    // 如果执行 then 时 Promise 实例的状态已经变化,那么就可以直接执行传入的参数
    if (this.status === STATUS_FULFILLED && onFulfilled) {
      onFulfilled(this.value)
    }
    if (this.status === STATUS_REJECTED && onRejected) {
      onRejected(this.reason)
    }
    // 如果在执行 then 的时候当前的状态还是 PENDING
    // 那么就加入队列中,等待执行 resolve、reject 的时候统一执行所有的队列
    if (this.status === STATUS_PENDING) {
      // 将任务放到相应队列中
      if (onFulfilled) this.resolveQueue.push(onFulfilled)
      if (onRejected) this.resolveQueue.push(onRejected)
    }
  }
}

3. 如果构造函数抛出了一个错误,then 的第二个参数也可以捕获到

Test Case

test('如果构造函数抛出了一个错误,then 的第二个参数也可以捕获到', () => {
  new _Promise(() => {
    throw new Error('error!')
  }).then(undefined, err => {
    expect(err).toEqual(new Error('error!'))
  })
})

Code

class _Promise {
  constructor(executor = () => {}) {
    this.status = STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.resolveQueue = []
    this.rejectQueue = []
    const resolve = value => {
      if (this.status === STATUS_PENDING) {
        this.status = STATUS_FULFILLED
        this.value = value
        if (this.resolveQueue.length)
          this.resolveQueue.forEach(item => item(this.value))
      }
    }
    const reject = reason => {
      if (this.status === STATUS_PENDING) {
        this.status = STATUS_REJECTED
        this.reason = reason
        if (this.rejectQueue.length)
          this.rejectQueue.forEach(item => item(this.reason))
      }
    }
    // try...catch 捕获一下错误
    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }
  then(onFulfilled, onRejected) {
    // then code 无变化
  }
}

4. 链式调用

Test Case

test('链式调用', () => {
  new _Promise(resolve => {
    resolve('success1')
  })
    .then(res => {
      expect(res).toBe('success1')
      return res + ' success2'
    })
    .then(res => {
      expect(res).toBe('success1 success2')
    })
  new _Promise((resolve, reject) => {
    reject('error1')
  })
    .then(undefined, err => {
      expect(err).toBe('error1')
      return err + ' error2'
    })
    .then(res => {
      expect(res).toBe('error1 error2')
    })
})

Code

_Promise {
  constructor(executor = () => {}) {
    // 构造函数无变化
  }
  then(onFulfilled, onRejected) {
    // 要想做到链式调用,就需要返回新的 Promise
    return new Promise((resolve, reject) => {
      if (this.status === STATUS_FULFILLED && onFulfilled) {
        // 将 onFulfilled 返回的值作为下一个 Promise resolve() 的值
        const value = onFulfilled(this.value)
        resolve(value)
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        // 这个也是同理
        const reason = onRejected(this.reason)
        resolve(reason)
      }
      if (this.status === STATUS_PENDING) {
        // 这里需要做一下处理了,因为这里队列是在构造函数中处理的
        // 所以需要转化一下
        if (onFulfilled)
          this.resolveQueue.push(param => {
            const value = onFulfilled(param)
            resolve(value)
          })
        if (onRejected)
          this.resolveQueue.push(param => {
            const reason = onRejected(param)
            resolve(reason)
          })
      }
    })
  }
}

5. 在链式调用的过程中出现任何错误,将由下面的 then 第二个参数处理

Test Case

test('在链式调用的过程中出现任何错误,将由下面的 then 第二个参数处理', () => {
  new _Promise((resolve, reject) => {
    resolve('success')
  })
    .then(res => {
      expect(res).toBe('success')
      throw new Error('error!')
    })
    .then(undefined, err => {
      expect(err).toEqual(new Error('error!'))
    })
})

Code

// 因为需要对 4 个地方同时进行 try...catch
// 重复代码,就可以抽离为工具函数了
function executeFnWithCatchError(fn, param, resolve, reject) {
  try {
    const result = fn(param)
    resolve(result)
  } catch (error) {
    reject(error)
  }
}

class _Promise {
  constructor(executor = () => {}) {
      // 构造函数无变化
  }
  then(onFulfilled, onRejected) {
    return new Promise((resolve, reject) => {
      if (this.status === STATUS_FULFILLED && onFulfilled) {
        // 在这里进行捕获
        executeFnWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        // 在这里进行捕获
        executeFnWithCatchError(onRejected, this.reason, resolve, reject)
      }
      if (this.status === STATUS_PENDING) {
        if (onFulfilled)
          this.resolveQueue.push(param => {
            // 在这里进行捕获
            executeFnWithCatchError(onFulfilled, param, resolve, reject)
          })
        if (onRejected)
          this.resolveQueue.push(param => {
            // 在这里进行捕获
            executeFnWithCatchError(onRejected, param, resolve, reject)
          })
      }
    })
  }
}

3.3 catch

1. catch 应该捕获上一个 Promise 实例的 reject

Test Case

test('catch 应该捕获上一个 Promise 实例的 reject ', () => {
  new _Promise((resolve, reject) => {
    reject('error')
  }).catch(err => {
    expect(err).toBe('error')
  })
  new _Promise((resolve, reject) => {
    resolve('success')
  })
    .then(() => {
      throw new Error('error')
    })
    .catch(err => {
      expect(err).toEqual(new Error('error'))
    })
})

Code

class _Promise {
  constructor(executor = () => {}) {
    // 构造函数无变化
  }
  then(onFulfilled, onRejected) {
    // then 方法无变化
  }
  // 新增实例方法 catch
  catch(onRejected) {
    // 这里其实可以直接复用 then 的逻辑
    // 将传入的数据作为 then 的第二个参数
    this.then(undefined, onRejected)
  }
}

2. catch 可以捕获最开始的 reject

Test Case

test('catch 可以捕获最开始的 reject ', () => {
  new Promise((resolve, reject) => {
    reject('error')
  })
    .then(res => {
      return res
    })
    .then(res => {
      return res
    })
    .catch(err => {
      console.log('error', err)
      expect(err).toBe('error')
    })
})

Code

class _Promise {
  constructor(executor = () => {}) {
    // 构造函数无变化
  }
  then(onFulfilled, onRejected) {
    // 针对这一情况,可以给两个参数写一个默认值
    onFulfilled = onFulfilled
      ? onFulfilled
      : value => {
          return value
        }
    onRejected = onRejected
      ? onRejected
      : reason => {
          throw new Error(reason)
        }
    return new Promise((resolve, reject) => {
      // 判断就可以删除掉了,因为传入的两个参数是必定有值的
      if (this.status === STATUS_FULFILLED) {
        executeFnWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === STATUS_REJECTED) {
        executeFnWithCatchError(onRejected, this.reason, resolve, reject)
      }
      if (this.status === STATUS_PENDING) {
        this.resolveQueue.push(param => {
          executeFnWithCatchError(onFulfilled, param, resolve, reject)
        })
        this.resolveQueue.push(param => {
          executeFnWithCatchError(onRejected, param, resolve, reject)
        })
      }
    })
  }
  catch(onRejected) {
    // catch 无变化
  }
}

3.4 finally

Test Case

test('无论 Promise 状态是满足还是拒绝,finally 都应该执行', () => {
  let finallyTimer = 0
  new _Promise(resolve => {
    resolve('hello world')
  }).finally(() => {
    finallyTimer++
  })
  expect(finallyTimer).toBe(1)
  new _Promise((resolve, reject) => {
    reject('hello world')
  }).finally(() => {
    finallyTimer++
  })
  expect(finallyTimer).toBe(2)
})

Code

class _Promise {
  constructor(executor = () => {}) {
    // 构造函数无变化
  }
  then(onFulfilled, onRejected) {
    // then 无变化
  }
  catch(onRejected) {
    // catch 无变化
  }
  // 新增实例方法 finally
  finally(onFinally) {
    // 复用 then 逻辑,传入 onFinally
    this.then(
      () => {
        onFinally()
      },
      () => {
        onFinally()
      }
    )
  }
}

3.5 resolve

resolve 是 Promise 的类方法,可以将传入的值作为resolve()的参数,即:

Promise.resolve("success")
// 等于下面
new Promise(resolve => {
    resolve('success')
})

Test Case

test('resolve 可以将一个传入的值作为 resolve() 的参数', () => {
  const data = { name: 'alex' }
  Promise.resolve(data).then(res => {
    expect(res).toEqual(data)
  })
})

Code

class _Promise {
  constructor(executor = () => {}) {
    // 构造函数无变化
  }
  then(onFulfilled, onRejected) {
    // then 无变化
  }
  catch(onRejected) {
    // catch 无变化
  }
  finally(onFinally) {
    // finally 无变化
  }
  // 新增类方法
  static resolve(data) {
    return new _Promise(resolve => resolve(data))
  }
}

3.6 reject

和 resolve 的逻辑是一样的

Test Case

test('reject 可以将传入的值作为 reject() 的参数', () => {
  _Promise.reject('error').catch(err => {
    expect(err).toBe('error')
  })
})

Code

class _Promise {
  constructor(executor = () => {}) {
    // 构造函数无变化
  }
  then(onFulfilled, onRejected) {
    // then 无变化
  }
  catch(onRejected) {
    // catch 无变化
  }
  finally(onFinally) {
    // finally 无变化
  }
  static resolve(data) {
    // resolve 无变化
  }
  // 新增类方法 reject
  static reject(data) {
    return new _Promise((resolve, reject) => reject(data))
  }
}

3.7 all

Test Case

test('all 方法接收队列,所有 fulfilled 即 fulfilled,一个 rejected 则 rejected', () => {
  function genPromise(index) {
    return new _Promise(resolve => {
      resolve('success' + index)
    })
  }
  const promiseQueue = [
    genPromise(0),
    genPromise(1),
    genPromise(2),
    genPromise(3),
  ]
  _Promise.all(promiseQueue).then(res => {
    expect(res).toEqual(['success0', 'success1', 'success2', 'success3'])
  })
  const promiseQueue2 = [
    ...promiseQueue,
    new _Promise((resolve, reject) => reject('error')),
  ]
  _Promise.all(promiseQueue2).catch(err => {
    expect(err).toBe('error')
  })
})

Code

class _Promise {
  constructor(executor = () => {}) {
    // 构造函数无变化
  }
  then(onFulfilled, onRejected) {
    // then 无变化
  }
  catch(onRejected) {
    // catch 无变化
  }
  finally(onFinally) {
    // finally 无变化
  }
  static resolve(data) {
    // resolve 无变化
  }
  static reject(data) {
    // reject 无变化
  }
  // 新增类方法
  static all(promiseQueue) {
    return new _Promise((resolve, reject) => {
      const result = []
      // 对队列进行遍历
      promiseQueue.forEach(promise => {
        promise
          .then(res => {
            result.push(res)
          })
          .catch(err => {
            // 任何一个 reject 那么就直接 reject
            reject(err)
          })
      })
      // 所有的 resolve,才 resolve
      resolve(result)
    })
  }
}

3.8 allSettled

Test Case

test('allSettled 无论 promise 队列是 fulfilled 还是 rejected,都会保存起来,并且只会是 fulfilled', () => {
  function genPromise(index) {
    return new Promise(resolve => {
      resolve('success' + index)
    })
  }
  const promiseQueue = [genPromise(0), genPromise(1), genPromise(2)]
  Promise.allSettled(promiseQueue).then(res => {
    expect(res).toEqual([
      { status: 'fulfilled', value: 'success0' },
      { status: 'fulfilled', value: 'success1' },
      { status: 'fulfilled', value: 'success2' },
    ])
  })
  const promiseQueue2 = [
    ...promiseQueue,
    new Promise((resolve, reject) => reject('error')),
  ]
  Promise.allSettled(promiseQueue2).catch(err => {
    expect(err).toEqual([
      { status: 'fulfilled', value: 'success0' },
      { status: 'fulfilled', value: 'success1' },
      { status: 'fulfilled', value: 'success2' },
      { status: 'rejected', reason: 'error' },
    ])
  })
})

Code

class _Promise {
  constructor(executor = () => {}) {
    // 构造函数无变化
  }
  then(onFulfilled, onRejected) {
    // then 无变化
  }
  catch(onRejected) {
    // catch 无变化
  }
  finally(onFinally) {
    // finally 无变化
  }
  static resolve(data) {
    // resolve 无变化
  }
  static reject(data) {
    // reject 无变化
  }
  static all(promiseQueue) {
    // all 无变化
  }
  // 新增类方法:allSettled
  static allSettled(promiseQueue) {
    return new _Promise(resolve => {
      const result = []
      // 遍历队列,满足 or 拒绝都加入返回队列中
      // 只是状态和 value/reason 不同
      promiseQueue.forEach(promise => {
        promise
          .then(res => {
            result.push({
              status: STATUS_FULFILLED,
              value: res,
            })
          })
          .catch(err => {
            result.push({
              status: STATUS_REJECTED,
              reason: err,
            })
          })
      })
      resolve(result)
    })
  }
}

3.9 race

Test Case

test('队列中哪个最先完成,那么 race 返回的实例就是什么状态', () => {
  function genPromise(delay, message, type = 'fulfilled') {
    if (type === 'fulfilled') {
      return new _Promise(resolve => {
        setTimeout(() => {
          resolve(message)
        }, delay)
      })
    }
    return new _Promise((resolve, reject) => {
      setTimeout(() => {
        reject(message)
      }, delay)
    }, delay)
  }
  const promiseQueue = [
    genPromise(200, 'success1'),
    genPromise(100, 'success2'),
    genPromise(300, 'success3'),
  ]
  _Promise.race(promiseQueue).then(res => {
    expect(res).toBe('success2')
  })
  const promiseQueue2 = [...promiseQueue, genPromise(50, 'error', 'rejected')]
  _Promise.race(promiseQueue2).catch(err => {
    expect(err).toBe('error')
  })
})

Code

class _Promise {
  constructor(executor = () => {}) {
    // 构造函数无变化
  }
  then(onFulfilled, onRejected) {
    // then 无变化
  }
  catch(onRejected) {
    // catch 无变化
  }
  finally(onFinally) {
    // finally 无变化
  }
  static resolve(data) {
    // resolve 无变化
  }
  static reject(data) {
    // reject 无变化
  }
  static all(promiseQueue) {
    // all 无变化
  }
  // 新增类方法:allSettled
  static allSettled(promiseQueue) {
    // allSettled 无变化
  }
    // 新增类方法 race
  static race(promiseQueue) {
    return new _Promise((resolve, reject) => {
      // 遍历队列
      promiseQueue.forEach(promise => {
        // 有一个改变了状态,那么整体就改变了状态
        promise
          .then(res => {
            resolve(res)
          })
          .catch(err => {
            reject(err)
          })
      })
    })
  }
}

3.10 any

Test Case

test('any 方法接收一个 Promise 队列,只要一个是 fulfilled 状态,就改变返回的实例状态,如果所有都是 rejected,也要等待所有执行完毕后,抛出一个错误', () => {
  function genPromise(delay, message, type = 'fulfilled') {
    if (type === 'fulfilled') {
      return new _Promise(resolve => {
        setTimeout(() => {
          resolve(message)
        }, delay)
      })
    }
    return new _Promise((resolve, reject) => {
      setTimeout(() => {
        reject(message)
      }, delay)
    }, delay)
  }
  const promiseQueue = [
    genPromise(100, 'error1', 'rejected'),
    genPromise(200, 'success1'),
    genPromise(300, 'error2', 'rejected'),
  ]
  _Promise
    .any(promiseQueue)
    .then(res => {
      expect(res).toBe('success1')
    })
    .catch(() => {})
  const promiseQueue2 = [
    genPromise(100, 'error11', 'rejected'),
    genPromise(200, 'error22', 'rejected'),
    genPromise(300, 'error33', 'rejected'),
  ]
  try {
    _Promise.any(promiseQueue2).catch(err => {})
  } catch (error) {
    expect(error).toEqual(new AggregateError('All promises were rejected'))
  }
})

Code

class _Promise {
  constructor(executor = () => {}) {
    // 构造函数无变化
  }
  then(onFulfilled, onRejected) {
    // then 无变化
  }
  catch(onRejected) {
    // catch 无变化
  }
  finally(onFinally) {
    // finally 无变化
  }
  static resolve(data) {
    // resolve 无变化
  }
  static reject(data) {
    // reject 无变化
  }
  static all(promiseQueue) {
    // all 无变化
  }
  static allSettled(promiseQueue) {
    // allSettled 无变化
  }
  static race(promiseQueue) {
    // race 无变化   
  }
  // 新增类方法 any
  static any(promiseQueue) {
    return new _Promise((resolve, reject) => {
      const reasons = []
      promiseQueue.forEach(promise => {
        promise
          .then(res => {
            // 只要有一个满足,那么就满足
            resolve(res)
          })
          .catch(err => {
            reasons.push(err)
          })
      })
      // 如果全部拒绝,那么就抛出一个错误
      if (reasons.length === promiseQueue.length) {
        throw new AggregateError()
      }
    })
  }
}

3.11 全部

最后,关于 Promise 的功能和 API 我们已经初步实现完毕了,当然,一些边界判断是没有加的。

让我们看一下全部代码吧:

const STATUS_PENDING = 'pending'
const STATUS_FULFILLED = 'fulfilled'
const STATUS_REJECTED = 'rejected'

function executeFnWithCatchError(fn, param, resolve, reject) {
  try {
    const result = fn(param)
    resolve(result)
  } catch (error) {
    reject(error)
  }
}

export class _Promise {
  constructor(executor = () => {}) {
    this.status = STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.resolveQueue = []
    this.rejectQueue = []
    const resolve = value => {
      if (this.status === STATUS_PENDING) {
        this.status = STATUS_FULFILLED
        this.value = value
        if (this.resolveQueue.length)
          this.resolveQueue.forEach(item => item(this.value))
      }
    }
    const reject = reason => {
      if (this.status === STATUS_PENDING) {
        this.status = STATUS_REJECTED
        this.reason = reason
        if (this.rejectQueue.length)
          this.rejectQueue.forEach(item => item(this.reason))
      }
    }
    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }
  then(onFulfilled, onRejected) {
    onFulfilled = onFulfilled
      ? onFulfilled
      : value => {
          return value
        }
    onRejected = onRejected
      ? onRejected
      : reason => {
          throw new Error(reason)
        }
    return new Promise((resolve, reject) => {
      if (this.status === STATUS_FULFILLED) {
        executeFnWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === STATUS_REJECTED) {
        executeFnWithCatchError(onRejected, this.reason, resolve, reject)
      }
      if (this.status === STATUS_PENDING) {
        this.resolveQueue.push(param => {
          executeFnWithCatchError(onFulfilled, param, resolve, reject)
        })
        this.resolveQueue.push(param => {
          executeFnWithCatchError(onRejected, param, resolve, reject)
        })
      }
    })
  }
  catch(onRejected) {
    this.then(undefined, onRejected)
  }
  finally(onFinally) {
    this.then(
      () => {
        onFinally()
      },
      () => {
        onFinally()
      }
    )
  }
  static resolve(data) {
    return new _Promise(resolve => resolve(data))
  }
  static reject(data) {
    return new _Promise((resolve, reject) => reject(data))
  }
  static all(promiseQueue) {
    return new _Promise((resolve, reject) => {
      const result = []
      promiseQueue.forEach(promise => {
        promise
          .then(res => {
            result.push(res)
          })
          .catch(err => {
            reject(err)
          })
      })
      resolve(result)
    })
  }
  static allSettled(promiseQueue) {
    return new _Promise(resolve => {
      const result = []
      promiseQueue.forEach(promise => {
        promise
          .then(res => {
            result.push({
              status: STATUS_FULFILLED,
              value: res,
            })
          })
          .catch(err => {
            result.push({
              status: STATUS_REJECTED,
              reason: err,
            })
          })
      })
      resolve(result)
    })
  }
  static race(promiseQueue) {
    return new _Promise((resolve, reject) => {
      promiseQueue.forEach(promise => {
        promise
          .then(res => {
            resolve(res)
          })
          .catch(err => {
            reject(err)
          })
      })
    })
  }
  static any(promiseQueue) {
    return new _Promise((resolve, reject) => {
      const reasons = []
      promiseQueue.forEach(promise => {
        promise
          .then(res => {
            resolve(res)
          })
          .catch(err => {
            reasons.push(err)
          })
      })
      if (reasons.length === promiseQueue.length) {
        throw new AggregateError()
      }
    })
  }
}

总结

本文详细讲解了 Promise 以及手写了 Promise 的逻辑,希望对你有所帮助

附完整源码:

(mini-promise 源码)[github.com/alexzhang10…]