手写Promise

简介: 手写Promise

35. 手写Promise

class MyPromise {
   
  constructor(executor) {
   
    this.state = "pending" // 状态
    this.value = undefined // 成功的值
    this.reason = undefined // 失败的原因
    this.onFulfilledFns = [] // 成功回调数组
    this.onRejectedFns = [] // 失败回调数组

    const resolve = (value) =>{
   
      if(this.state === "pending") {
   
        this.state = "fulfilled"
        this.value = value
        this.onFulfilledFns.forEach(fn => fn(this.value))
      }
    }
    const reject = (reason) =>{
   
      if(this.state === "pending") {
   
        this.state = "rejected"
        this.reason = reason
        this.onRejectedFns.forEach(fn => fn(this.reason))
      }
    }

    try {
   
      executor(resolve, reject)
    } catch(err) {
   
      reject(err)
    }
  }
  // then方法 将在当前promise解决后调用的onFulfilled和在当前promise拒绝后调用的onRejected附加到当前promise,并返回一个新的promise。如果onFulfilled或onRejected返回一个值,则该值将作为新promise的解决值;如果onFulfilled或onRejected抛出异常,则新promise将拒绝并且原因为该异常。
  then(onFulfilled, onRejected) {
   
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value;
    onRejected = typeof onRejected === 'function' ? onRejected : (reason) => {
    throw reason; };

    return new MyPromise((resolve, reject) => {
   
      if(this.state === "fulfilled") {
   
        try {
   
          const value = onFulfilled(this.value)
          resolve(value)
        } catch(err) {
   
          reject(err)
        }
      } else if(this.state === "rejected") {
   
        try {
   
          const reason = onRejected(this.reason)
          resolve(reason)
        } catch(err) {
   
          reject(err)
        }
      } else {
   
        this.onFulfilledFns.push(() => {
   
          try {
   
            const value = onFulfilled(this.value)
            resolve(value)
          } catch(err) {
   
            reject(err)
          }
        })
        this.onRejectedFns.push(() => {
   
          try {
   
            const reason = onRejected(this.reason)
            resolve(reason)
          } catch(err) {
   
            reject(err)
          }
        })
      }
    })
  }
  // catch方法  与then方法相似,将一个拒绝处理程序onRejected附加到当前promise并返回一个新promise。如果当前promise被拒绝,则调用onRejected;否则,新promise将解决并且解决值将等于当前promise的解决值。
  catch(onRejected) {
   
    this.then(null, onRejected)
  }
  // finally方法 增加一个onFinally回调到当前promise,当前promise解决或拒绝时都将调用onFinally。
  finally(onFinally) {
   
    this.then(() => {
   
      onFinally()
    }, () => {
   
      onFinally()
    })
  }
  // resolve方法 返回一个状态为fulfilled的promise,其值为value
  static resolve(value) {
   
    return new MyPromise((resolve) => resolve(value))
  }
  // reject方法 返回一个状态为rejected的promise,其原因为reason
  static reject(reason) {
   
    return new MyPromise((resolve, reject) => reject(reason))
  }
  // all方法 传入一个promise数组,并返回一个新promise。当传递的所有promise都解决时,新promise将解决,并且其解决值为一个包含所有传递promise的解决值的数组。如果传递的任何promise被拒绝,则新promise将拒绝,并且原因为传递的第一个被拒绝promise的原因。
  static all(promises) {
   
    return new MyPromise((resolve, reject) => {
   
      const values = []
      promises.forEach((promise) => {
   
        promise.then(res => {
   
          values.push(res)
          if(values.length === promises.length){
   
            resolve(values)
          }
        }, reject)
      })
    })
  }
  // allSettled方法  传入一个promise数组,并返回一个新promise。该promise将在传递的所有promise都解决或拒绝后解决,并返回一个数组,该数组包含所有promise的结果对象,其中每个结果对象都具有status属性,其值为fulfilled或rejected,以及一个value或reason属性,分别为解决值或拒绝原因。
  static allSettled(promises) {
   
    return new MyPromise((resolve, reject) => {
   
      const values = []
      promises.forEach((promise) => {
   
        promise.then(res => {
   
          values.push({
    status: "fulfilled", value: res })
          if(values.length === promises.length) {
   
            resolve(values)
          }
        }, err => {
   
          values.push({
    status: "rejected", value: err })
          if(values.length === promises.length) {
   
            resolve(values)
          }
        })
      })
    })
  }
  // race方法 传入一个promise数组,并返回一个新promise。当传递的任何promise解决或拒绝时,新promise将解决或拒绝,并且其值将等于传递的第一个promise的解决值或拒绝原因。
  static race(promises) {
   
    return new MyPromise((resolve, reject) => {
   
      promises.forEach(promise => {
   
        promise.then(resolve, reject)
      })
    })
  }
  // any方法  传入一个promise数组,并返回一个新promise。该promise将在传递的任何promise被解决后立即解决,并返回传递的第一个被解决的promise的解决值。如果所有传递的promise都被拒绝,则新promise将拒绝,并且原因为一个AggregateError对象,其中包含所有被拒绝的promise的原因。
  static any(promises) {
   
    const errors = []
    return new MyPromise((resolve, reject) => {
   
      promises.forEach(promise => {
   
        promise.then(resolve, err => {
   
          errors.push(err)
          if(errors.length === promises.length) {
   
            reject(new AggregateError(errors))
          }
        })
      })
    })
  }
}
相关文章
|
6月前
|
前端开发 JavaScript
在JavaScript中,什么是promise、怎么使用promise、怎么手写promise
在JavaScript中,什么是promise、怎么使用promise、怎么手写promise
99 4
|
前端开发
手写基础 promise
手写基础 promise
64 0
|
存储 前端开发
|
前端开发
Promise的用法&原理&手写实现-2
Promise的用法&原理&手写实现-2
40 1
|
6月前
|
前端开发 JavaScript API
手写promise
手写promise
40 0
|
6月前
|
存储 前端开发 JavaScript
面试官:请手写一个Promise
面试官:请手写一个Promise
|
前端开发 JavaScript API
Promise的用法&原理&手写实现-1
Promise的用法&原理&手写实现-1
54 0
|
前端开发 vr&ar
自定义手写Promise
手写函数版和类版Promise
55 0
|
前端开发 算法 安全
前端面试100道手写题(1)—— 手写Promise实现
今年的金三银四面试,遇到了很多新的面试八股文,其实心里对手写题或者算法题有一定抵触,因为实际工作中基本上就不会用到这些东西,但是正因为这些基础八股文,才能真正验证一个人对技术有多热爱的程度。也有可能近几年没有对这些基础知识进行巩固,所以干脆一狠心,先立个flag, 准备完成100道手写题。
254 0
|
缓存 前端开发 JavaScript
带你手写 Promise,别再死记硬背了!!!(上)
带你手写 Promise,别再死记硬背了!!!
1066 1