手写Promise

72 阅读9分钟

1. 手写 Promise

1.1 实现 MYPromise

  • 正常的 Promise 是可以传入两个回调函数的:一个成功回调,一个失败回调,所以我们实现的这个类应该是包含这两个回调的;
  • resolve 和 reject 函数二者是互斥的,即:执行完一个之后,另外一个是不执行的,所以我们需要使用状态来记录二者回调时的执行状态;
  • 此外,函数是可以执行 then 回调的,所以我们需要保存一开始二者传入的值。
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class MYPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined

    const resolve = value => {
      if (this.status !== PROMISE_STATUS_PENDING) return
      this.status = PROMISE_STATUS_FULFILLED
      this.value = value
      console.log('resolve')
    }

    const reject = reason => {
      if (this.status !== PROMISE_STATUS_PENDING) return
      this.status = PROMISE_STATUS_REJECTED
      this.reason = reason
      console.log('reject')
    }

    executor(resolve, reject)
  }
}

const promise = new MYPromise((resolve, reject) => {
  resolve(111)
  reject(222)
})

promise.then(
  res => {},
  err => {}
)

1.2 基础版 then 方法

  1. setTimeout
  • then 方法也是接收两个回调函数的,一个成功回调,一个失败回调。所以我们使用两个变量来记录这两个回调,使用下述代码时会出现异常,就是在 resolve 或者 reject 时提示 this.onFulfilled 或者 this.onRejected 是 undefined 无法执行函数操作,因此我们首先考虑的是将其加入宏任务队列中。
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class MYPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilled = undefined
    this.onRejected = undefined

    const resolve = value => {
      // setTimeout(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_FULFILLED
        this.value = value
        console.log('resolve')
        this.onFulfilled(this.value)
      // }, 0)
    }

    const reject = reason => {
      // setTimeout(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_REJECTED
        this.reason = reason
        console.log('reject')
        this.onRejected(this.reason)
      // }, 0)
    }

    executor(resolve, reject)
  }

  then(onFulfilled, onRejected) {
    this.onFulfilled = onFulfilled
    this.onRejected = onRejected
  }
}

const promise = new MYPromise((resolve, reject) => {
  reject(222)
  resolve(111)
})

promise.then(
  res => {
    console.log('res: ', res)
  },
  err => {
    console.log('err: ', err)
  }
)
  1. queueMicrotash

使用如下代码可以正确地执行 then 方法了,但是会存在两个问题:

    1. 无法多次执行 then 方法;
    1. then 方法无法实现链式回调
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class MYPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilled = undefined
    this.onRejected = undefined

    const resolve = value => {
      if (this.status !== PROMISE_STATUS_PENDING) return
      this.status = PROMISE_STATUS_FULFILLED
      queueMicrotask(() => {
        this.value = value
        this.onFulfilled(this.value)
      })
    }

    const reject = reason => {
      if (this.status !== PROMISE_STATUS_PENDING) return
      this.status = PROMISE_STATUS_REJECTED
      queueMicrotask(() => {
        this.reason = reason
        this.onRejected(this.reason)
      })
    }

    executor(resolve, reject)
  }

  then(onFulfilled, onRejected) {
    this.onFulfilled = onFulfilled
    this.onRejected = onRejected
  }
}

const promise = new MYPromise((resolve, reject) => {
  resolve(111)
  reject(222)
})

promise.then(
  res => {
    console.log('res: ', res)
  },
  err => {
    console.log('err: ', err)
  }
)

/**
 * 这份代码存在的几个问题:
 * 1. 无法多次执行 then 方法
 * 2. then 方法不能链式调用
 */

promise
  .then(
    res => {
      console.log('res1: ', res)
    },
    err => {
      console.log('err1: ', err)
    }
  )
  .then(() => {})

1.3 then 方法多次执行

为保证 then 方法多次执行,我们需要将上述的 this.onFulfilled 和 this.onRejected 定义为函数。

  • 执行 then 方法时,如果状态已经确定,我们只需执行正确地回调即可;
  • 如果状态还未确定,我们需要将需要执行的回调函数加入到 this.onFulfilled 或 this.onRejected 的函数中,然后在 resolve 或者 reject 中依次遍历方法即可。
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class MYPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilledFns = []
    this.onRejectedFns = []

    const resolve = value => {
      queueMicrotask(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_FULFILLED
        this.value = value
        this.onFulfilledFns.map(fn => fn(this.value))
      })
    }

    const reject = reason => {
      queueMicrotask(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_REJECTED
        this.reason = reason
        this.onRejectedFns.map(fn => fn(this.reason))
      })
    }

    executor(resolve, reject)
  }

  then(onFulfilled, onRejected) {
    // 1. 如果在 then 调用的时候,状态已经确定 --> 为了解决 setTimeout 延时中的 then 回调
    if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
      onFulfilled(this.value)
    }
    if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
      onRejected(this.reason)
    }
    // 2. 将成功和失败的回掉函数放入数组中
    if (this.status === PROMISE_STATUS_PENDING) {
      if (onFulfilled instanceof Function) {
        this.onFulfilledFns.push(onFulfilled)
      }
      if (onRejected instanceof Function) {
        this.onRejectedFns.push(onRejected)
      }
    }
  }
}

const promise = new MYPromise((resolve, reject) => {
  resolve(111)
  reject(222)
})

promise.then(
  res => {
    console.log('res1: ', res)
  },
  err => {
    console.log('err1: ', err)
  }
)

promise.then(
  res => {
    console.log('res2: ', res)
  },
  err => {
    console.log('err2: ', err)
  }
)

setTimeout(() => {
  promise.then(res => {
    console.log('res3: ', res)
  })
}, 1000)

1.4 then 方法链式调用

为保证 then 方法可以链式调用,我们需要在 then 函数中返回我们自定义的 MYPromise 方法,并且在执行完回调后拿到值并使用 resolve 或者 reject 返回对应的值。

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class MYPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilledFns = []
    this.onRejectedFns = []

    const resolve = value => {
      queueMicrotask(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_FULFILLED
        this.value = value
        this.onFulfilledFns.map(fn => fn(this.value))
      })
    }

    const reject = reason => {
      queueMicrotask(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_REJECTED
        this.reason = reason
        this.onRejectedFns.map(fn => fn(this.reason))
      })
    }

    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }

  then(onFulfilled, onRejected) {
    return new MYPromise((resolve, reject) => {
      // 1. 如果在 then 调用的时候,状态已经确定 --> 为了解决 setTimeout 延时中的 then 回调
      if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
        try {
          const value = onFulfilled(this.value)
          resolve(value)
        } catch (err) {
          reject(err)
        }
      }
      if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
        try {
          const reason = onRejected(this.reason)
          resolve(reason)
        } catch (err) {
          reject(err)
        }
      }
      // 2. 将成功和失败的回掉函数放入数组中
      if (this.status === PROMISE_STATUS_PENDING) {
        if (onFulfilled instanceof Function) {
          // 如果直接将回掉函数放入到数组中,那么我们无法拿到回掉函数的执行结果,因此无法做到链式调用,于是考虑在外层包裹一层回掉函数
          // this.onFulfilledFns.push(onFulfilled)
          this.onFulfilledFns.push(() => {
            try {
              const value = onFulfilled(this.value)
              resolve(value)
            } catch (err) {
              reject(err)
            }
          })
        }
        if (onRejected instanceof Function) {
          this.onRejectedFns.push(() => {
            try {
              const reason = onRejected(this.reason)
              resolve(reason)
            } catch (err) {
              reject(err)
            }
          })
        }
      }
    })
  }
}

const promise = new MYPromise((resolve, reject) => {
  // resolve(111)
  // reject(222)
  throw new Error('err message')
})

promise
  .then(
    res => {
      console.log('res1: ', res)
      // return 'aaaa'
      throw new Error('err message')
    },
    err => {
      console.log('err1: ', err)
      // return 'bbbb'
      throw new Error('err message')
    }
  )
  .then(
    res => {
      console.log('res2: ', res)
    },
    err => {
      console.log('err2: ', err)
    }
  )

由于 try catch 在此代码中多次出现,我们可以考虑将其封装为一个函数:

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

function execFunctionWithCatchError(execFunc, value, resolve, reject) {
  try {
    const result = execFunc(value)
    resolve(result)
  } catch (err) {
    reject(err)
  }
}

class MYPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilledFns = []
    this.onRejectedFns = []

    const resolve = value => {
      queueMicrotask(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_FULFILLED
        this.value = value
        this.onFulfilledFns.map(fn => fn(this.value))
      })
    }

    const reject = reason => {
      queueMicrotask(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_REJECTED
        this.reason = reason
        this.onRejectedFns.map(fn => fn(this.reason))
      })
    }

    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }

  then(onFulfilled, onRejected) {
    return new MYPromise((resolve, reject) => {
      // 1. 如果在 then 调用的时候,状态已经确定 --> 为了解决 setTimeout 延时中的 then 回调
      if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
      }
      // 2. 将成功和失败的回掉函数放入数组中
      if (this.status === PROMISE_STATUS_PENDING) {
        if (onFulfilled instanceof Function) {
          // 如果直接将回掉函数放入到数组中,那么我们无法拿到回掉函数的执行结果,因此无法做到链式调用,于是考虑在外层包裹一层回掉函数
          // this.onFulfilledFns.push(onFulfilled)
          this.onFulfilledFns.push(() => {
            execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
          })
        }
        if (onRejected instanceof Function) {
          this.onRejectedFns.push(() => {
            execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
          })
        }
      }
    })
  }
}

const promise = new MYPromise((resolve, reject) => {
  // resolve(111)
  reject(222)
  // throw new Error('err message')
})

promise
  .then(
    res => {
      console.log('res1: ', res)
      return 'aaaa'
      // throw new Error('err message')
    },
    err => {
      console.log('err1: ', err)
      return 'bbbb'
      // throw new Error('err message')
    }
  )
  .then(
    res => {
      console.log('res2: ', res)
    },
    err => {
      console.log('err2: ', err)
    }
  )

1.5 catch 方法

直接调用写好的 then 方法即可,第一个参数为 undefined;然后在 then 方法中对 onRejected 方法进行改写一下即可。

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

function execFunctionWithCatchError(execFunc, value, resolve, reject) {
  try {
    const result = execFunc(value)
    resolve(result)
  } catch (err) {
    reject(err)
  }
}

class MYPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilledFns = []
    this.onRejectedFns = []

    const resolve = value => {
      queueMicrotask(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_FULFILLED
        this.value = value
        this.onFulfilledFns.map(fn => fn(this.value))
      })
    }

    const reject = reason => {
      queueMicrotask(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_REJECTED
        this.reason = reason
        this.onRejectedFns.map(fn => fn(this.reason))
      })
    }

    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }

  then(onFulfilled, onRejected) {
    onRejected = onRejected || (err => reject(err))

    return new MYPromise((resolve, reject) => {
      // 1. 如果在 then 调用的时候,状态已经确定 --> 为了解决 setTimeout 延时中的 then 回调
      if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
      }
      // 2. 将成功和失败的回掉函数放入数组中
      if (this.status === PROMISE_STATUS_PENDING) {
        if (onFulfilled instanceof Function) {
          // 如果直接将回掉函数放入到数组中,那么我们无法拿到回掉函数的执行结果,因此无法做到链式调用,于是考虑在外层包裹一层回掉函数
          // this.onFulfilledFns.push(onFulfilled)
          this.onFulfilledFns.push(() => {
            execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
          })
        }

        if (onRejected instanceof Function) {
          this.onRejectedFns.push(() => {
            execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
          })
        }
      }
    })
  }

  catch(onRejected) {
    // 这样一来,我们在 catch 中执行的回调相当于是第一个 then 方法的返回函数,
    // 但是由于第一层 catch 是 undefined,所以我们需要再 then 方法中重新定义 onRejected 方法。
    this.then(undefined, onRejected)
  }
}

const promise = new MYPromise((resolve, reject) => {
  // resolve(111)
  reject(222)
  // throw new Error('err message')
})

promise
  .then(res => {
    console.log('res1: ', res)
  })
  .catch(err => {
    console.log('err1: ', err)
  })

1.6 finally 方法

  • 由于我们可能需要再 finally 方法调用对应的 then 方法返回的值,所以我们需要将 onFulfilled 值进行改写;
  • catch 也需要返回一个 MYPromise
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

function execFunctionWithCatchError(execFunc, value, resolve, reject) {
  try {
    const result = execFunc(value)
    resolve(result)
  } catch (err) {
    reject(err)
  }
}

class MYPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilledFns = []
    this.onRejectedFns = []

    const resolve = value => {
      queueMicrotask(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_FULFILLED
        this.value = value
        this.onFulfilledFns.map(fn => fn(this.value))
      })
    }

    const reject = reason => {
      queueMicrotask(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_REJECTED
        this.reason = reason
        this.onRejectedFns.map(fn => fn(this.reason))
      })
    }

    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }

  then(onFulfilled, onRejected) {
    onRejected =
      onRejected ||
      (err => {
        throw err
      })

    onFulfilled =
      onFulfilled ||
      (value => {
        return value
      })

    return new MYPromise((resolve, reject) => {
      // 1. 如果在 then 调用的时候,状态已经确定 --> 为了解决 setTimeout 延时中的 then 回调
      if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
      }
      // 2. 将成功和失败的回掉函数放入数组中
      if (this.status === PROMISE_STATUS_PENDING) {
        if (onFulfilled instanceof Function) {
          // 如果直接将回掉函数放入到数组中,那么我们无法拿到回掉函数的执行结果,因此无法做到链式调用,于是考虑在外层包裹一层回掉函数
          // this.onFulfilledFns.push(onFulfilled)
          this.onFulfilledFns.push(() => {
            execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
          })
        }

        if (onRejected instanceof Function) {
          this.onRejectedFns.push(() => {
            execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
          })
        }
      }
    })
  }

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

  finally(onFinally) {
    this.then(
      () => {
        onFinally()
      },
      () => {
        onFinally()
      }
    )
  }
}

const promise = new MYPromise((resolve, reject) => {
  resolve(111)
  // reject(222)
  // throw new Error('err message')
})

promise
  .then(res => {
    console.log('res1: ', res)
    return 'aaa'
  })
  .then(res => {
    console.log('res2: ', res)
  })
  .catch(err => {
    console.log('err1: ', err)
  })
  .finally(() => {
    console.log('finally')
  })

1.7 其他类方法(resolve、reject、all、allSettled、race、any)

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

function execFunctionWithCatchError(execFunc, value, resolve, reject) {
  try {
    const result = execFunc(value)
    resolve(result)
  } catch (err) {
    reject(err)
  }
}

class MYPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilledFns = []
    this.onRejectedFns = []

    const resolve = value => {
      queueMicrotask(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_FULFILLED
        this.value = value
        this.onFulfilledFns.map(fn => fn(this.value))
      })
    }

    const reject = reason => {
      queueMicrotask(() => {
        if (this.status !== PROMISE_STATUS_PENDING) return
        this.status = PROMISE_STATUS_REJECTED
        this.reason = reason
        this.onRejectedFns.map(fn => fn(this.reason))
      })
    }

    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }

  then(onFulfilled, onRejected) {
    onRejected =
      onRejected ||
      (err => {
        throw err
      })

    onFulfilled =
      onFulfilled ||
      (value => {
        return value
      })

    return new MYPromise((resolve, reject) => {
      // 1. 如果在 then 调用的时候,状态已经确定 --> 为了解决 setTimeout 延时中的 then 回调
      if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
      }
      // 2. 将成功和失败的回掉函数放入数组中
      if (this.status === PROMISE_STATUS_PENDING) {
        if (onFulfilled instanceof Function) {
          // 如果直接将回掉函数放入到数组中,那么我们无法拿到回掉函数的执行结果,因此无法做到链式调用,于是考虑在外层包裹一层回掉函数
          // this.onFulfilledFns.push(onFulfilled)
          this.onFulfilledFns.push(() => {
            execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
          })
        }

        if (onRejected instanceof Function) {
          this.onRejectedFns.push(() => {
            execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
          })
        }
      }
    })
  }

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

  finally(onFinally) {
    this.then(
      () => {
        onFinally()
      },
      () => {
        onFinally()
      }
    )
  }

  static resolve(value) {
    return new MYPromise(resolve => resolve(value))
  }

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

  static all(promises) {
    return new MYPromise((resolve, reject) => {
      const values = []
      promises.map(promise => {
        promise
          .then(res => {
            values.push(res)
            if (values.length === promises.length) {
              resolve(values)
            }
          })
          .catch(err => {
            reject(err)
          })
      })
    })
  }

  static allSettled(promises) {
    const values = []
    return new MYPromise(resolve => {
      promises.map(promise => {
        promise
          .then(res => {
            values.push({ status: PROMISE_STATUS_FULFILLED, value: res })
            if (values.length === promises.length) {
              resolve(values)
            }
          })
          .catch(err => {
            values.push({ status: PROMISE_STATUS_REJECTED, value: err })
            if (values.length === promises.length) {
              resolve(values)
            }
          })
      })
    })
  }

  static race(promises) {
    return new MYPromise((resolve, reject) => {
      promises.map(promise => {
        promise.then(resolve, reject)
      })
    })
  }

  static any(promises) {
    // resolve 必须等到有一个成功的结果
    // reject 所有的都失败才执行 reject
    const reasons = []
    return new MYPromise((resolve, reject) => {
      promises.map(promise => {
        promise.then(resolve, err => {
          reasons.push(err)
          if (reasons.length === promises.length) {
            reject(new AggregateError(reasons))
          }
        })
      })
    })
  }
}

const promise = new MYPromise((resolve, reject) => {
  resolve(111)
  // reject(222)
  // throw new Error('err message')
})

promise
  .then(res => {
    console.log('res1: ', res)
    return 'aaa'
  })
  .then(res => {
    console.log('res2: ', res)
  })
  .catch(err => {
    console.log('err1: ', err)
  })
  .finally(() => {
    console.log('finally')
  })

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(111)
  }, 1000)
})
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(222)
  }, 2000)
})
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(333)
  }, 3000)
})
MYPromise.all([p1, p2, p3])
  .then(res => {
    console.log(res)
  })
  .catch(err => {
    console.log(err)
  })

MYPromise.allSettled([p1, p2, p3])
  .then(res => {
    console.log(res)
  })
  .catch(err => {
    console.log(err)
  })

MYPromise.race([p1, p2, p3])
  .then(res => {
    console.log(res)
  })
  .catch(err => {
    console.log(err)
  })

MYPromise.any([p1, p2, p3])
  .then(res => {
    console.log(res)
  })
  .catch(err => {
    console.log('errs:', err.errors)
  })