Bootstrap

js之手写promise

一、什么是promise?

promise是一个对异步操作进行封装并返回的其结果的构造函数;
使代码更简洁,避免回调地狱。
promise 特点:
1、执行了resolve,Promise状态会变成fulfilled
2、执行了reject,Promise状态会变成rejected
3、Promise只以第一次为准,第一次成功就永久为fulfilled,第一次失败就永远状态为rejected
4、Promise中有throw的话,就相当于执行了reject

二、MyPromise 的实现

class MyPromise {
  constructor(executor){
    // 初始化值
    this.initValue()
    // 初始化this
    this.initBind()
    // 存放异步Promise的回调函数
    this.onFulfilledCallbacks = []
    this.onRejectedCallbacks = []
    try {
      executor(this.resolve,this.reject)
    } catch (e) {
      this.reject(e)
    }
  }
  initBind(){
    // 初始化this绑定
    this.resolve = this.resolve.bind(this)
    this.reject = this.reject.bind(this)
  }
  initValue() {
    // 初始化状态和结果
    this.PromiseResult = null
    this.PromiseState = 'pending'
  }
  resolve(value){
    // 成功的回调
    // 状态不可逆
    if(this.PromiseState !== 'pending') return
    this.PromiseState = 'fulfilled'
    this.PromiseResult = value
    while(this.onFulfilledCallbacks.length){
      this.onFulfilledCallbacks.shift()(this.PromiseResult)
    }
  }
  reject(reason){
    // 失败的回调
    // 状态不可逆
    if(this.PromiseState !== 'pending') return
    this.PromiseState = 'reject'
    this.PromiseResult = reason
    while(this.onRejectedCallbacks.length){
      this.onRejectedCallbacks.shift()(this.PromiseResult)
    }
  }
  then(onFulfilled, onRejected){
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

    // then()方法需要返回一个Promise,才能链式 .then 操作

    var thenPromise = new MyPromise((resolve,reject) => {
      const resolvePromise = cb =>{
        // 实现then()方法的异步功能
        setTimeout(()=>{
          try {
            const x = cb(this.PromiseResult)
            debugger
            if(x === thenPromise){
              // 不能返回自身
              throw new Error('不能返回自身')
            }
            if(x instanceof MyPromise){
              x.then(resolve,reject)
            } else {
              resolve(x)
            } 
          } catch (err){
            // 处理报错
            reject(err)
            throw new Error(err)
          }
        })
      }
      if(this.PromiseState === 'fulfilled'){
        // onFulfilled(this.PromiseResult)
        resolvePromise(onFulfilled)
      } else if(this.PromiseState === 'reject') {
        // onRejected(this.PromiseResult)
        resolvePromise(onRejected)
      } else if(this.PromiseState === 'pending') {
        // this.onFulfilledCallbacks.push(onFulfilled.bind(this))
        // this.onRejectedCallbacks.push(onRejected.bind(this))
        // 异步Promise存储回调函数
        this.onFulfilledCallbacks.push(resolvePromise.bind(this,onFulfilled))
        this.onRejectedCallbacks.push(resolvePromise.bind(this,onRejected))
      }

    })

    // 返回包装的 Promise
    return thenPromise

  }
  // all 
  // 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
  // 如果所有Promise都成功,则返回成功结果数组
  // 如果有一个Promise失败,则返回这个失败结果
  static all(promises){
    const result = []
    let count = 0
    return new MyPromise((resolve,reject)=>{
      const addData = (index,value) =>{
        result[index] = value
        count ++
        if(count === promises.length) resolve(result)
      }
      promises.forEach((promise,index)=>{
        if(promise instanceof MyPromise){
          promise.then((res) =>{
            addData(index,res)
          },err => reject(err))
        }else {
          addData(index,promise)
        }
      })
    })
  }
  // race
  // 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
  // 哪个Promise最快得到结果,就返回那个结果,无论成功或失败
  static race(promises){
    return new MyPromise((resolve,reject)=>{
      promises.forEach(promise=>{
        if(promise instanceof MyPromise){
          promise.then(res=>{
            resolve(res)
          },err =>{
            reject(err)
          })
        } else {
          resolve(promise)
        }
      })
    })
  }
  // any
  // any 和 all 相反
  // 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
  // 如果有一个Promise成功,则返回这个成功结果
  // 如果所有Promise都失败,则报错
  static any(promises){
    return new MyPromise((resolve,reject)=>{
      let count = 0
      promises.forEach(promise=>{
        if(promise instanceof MyPromise){
          promise.then(res=>{
            resolve(res)
          },err=>{
            count ++
            if(count === promises.length){
              reject(err)
            }
          })
        }
      })
    })
  }
}
;