手写Promise总结

86 阅读2分钟
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULLFILLED = 'fullfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

function executeFunWithCatcherError(exeFn, value, resolve, reject) {
  try {
    const result = exeFn(value)
    resolve(result)
  } catch (err) {
    reject(err)
  }
}

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

    this.onFulfilledCallbacks = []
    this.onRejectedCallbacks = []
    const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDING) return
          this.status = PROMISE_STATUS_FULLFILLED
          this.value = value
          // console.log('resolve被调用')
          this.onFulfilledCallbacks.forEach(fn => {
            fn(this.value)
          })
        })
      }
    }

    const reject = (reason) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDING) return
          this.status = PROMISE_STATUS_REJECTED
          this.reason = reason
          // console.log('reject被调用')
          this.onRejectedCallbacks.forEach(fn => {
            fn(this.reason)
          })
        })
      }
    }

    executor(resolve, reject)
  }

  then(onfullfilled, onrejected) {

    // 在catch中调用的then返回的是一个新的Promsie
    onrejected = onrejected || (err => {throw err})
    onfullfilled = onfullfilled || (value => value)
    // 多个then需要将函数放入数组中

    // then返回的是一个promise
    return new MyPromise((resolve, reject) => {
      // 判断状态,如果不是pending直接执行
      if (this.status === PROMISE_STATUS_FULLFILLED && onfullfilled) {
        executeFunWithCatcherError(onfullfilled, this.value, resolve, reject)
      }

      if (this.status === PROMISE_STATUS_REJECTED && onrejected) {
        executeFunWithCatcherError(onrejected, this.reason, resolve, reject)
      }

      if (this.status === PROMISE_STATUS_PENDING) {
        this.onFulfilledCallbacks.push(() => {
          // try {
          //   const value = onfullfilled(this.value)
          //   resolve(value)
          // } catch (err) {
          //   reject(err)
          // }
          if (onfullfilled)executeFunWithCatcherError(onfullfilled, this.value, resolve, reject)
        })
        this.onRejectedCallbacks.push(() => {
          // try {
          //   const reason = onrejected(this.reason)
          //   resolve(reason)
          // } catch (err) {
          //   reject(err)
          // }
          if (onrejected)executeFunWithCatcherError(onrejected, this.reason, resolve, reject)
        })
      }
    })
  }

  catch(onrejected) {
    // 返回的是一个新的Promise
    return this.then(undefined, onrejected)
  }
  finally(onFinally) {
    this.then(() => {
      onFinally()
    }, () => {
      onFinally()
    })
  }
  static resolve(value) {
    return new MyPromise((resolve, reject) => {
      resolve(value)
    })
  }

  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason)
    })
  }
  static all(promises) {
    return new MyPromise((resolve, reject) => {
      let values = []
      promises.forEach(promise => {
        promise.then(res => {
          values.push(res)
          if (values.length === promises.length) {
            resolve(values)
          }
        }, err => {
          reject(err)
        })
      })
    })
  }

  static allSettled(promises) {
    return new MyPromise((resolve, reject) => {
      let values = []
      promises.forEach(promise => {
        promise.then(res => {
          values.push({status: PROMISE_STATUS_FULLFILLED, value: res})
          if (values.length === promises.length) {
            resolve(values)
          }
        }).catch(err => {
          values.push({status: PROMISE_STATUS_REJECTED, reason: err})
          if (values.length === promises.length) {
            resolve(values)
          }
        })
      })
    })
  }
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach(promise => {
        promise.then(res => {
          resolve(res)
        }, err => {
          reject(err)
        })
      })
    })
  }

  static any(promises) {
    return new MyPromise((resolve, reject) => {
      // 只能等到一个成功的结果
      // 如果全部是错误的才执行reject
      let reasons = []
      promises.forEach(promise => {
        promise.then(res => {
          resolve(res)
        }, err => {
          reasons.push(err)
          if (reasons.length === promises.length) {
            reject(new AggregateError(reasons))
          }
        })
      })
    })
  }
}



// const promise = new MyPromise((resolve, reject) => {
//   resolve('111111')
//   // reject('2222222')
// })

const p1 = new MyPromise((resolve, reject) =>{ setTimeout(() => {reject('111111')}, 1000) })
const p2 = new MyPromise((resolve, reject) =>{ setTimeout(() => {reject('22222222')}, 2000) })
const p3 = new MyPromise((resolve, reject) =>{ setTimeout(() => {reject('333333333')}, 3000) })

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

// MyPromise.reject('银峰11111').then(res => {
//   console.log(res)
// }).catch(err => {
//   console.log('err', err)
// })


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

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

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


// 需求
// 多个then执行
// settimeout中执行promise
// 多个then链式调用

// catch
// promise.then(res => {
//   console.log('res', res)
// }).catch(err => {
//   console.log('err2', err)
// }).finally(() => {
//   console.log('最后执行')
// })