读源码(四)—— js Promise

写了一些示例还有仿源码自己实现一个简单的MyPromise,主要内容都在代码注释中:

class PromiseTest {
  static test1() {
    const p = new Promise((resolve, reject) => {
      // resolve('result1')
      reject(new Error('error1'))
    })

    p.then(result => {
      console.log(result)
    }, error => {
      console.log(error.message)
    })
  }

  static test2() {
    const p = new Promise((resolve, reject) => {
      resolve('result2')
      // reject(new Error('error2'))
    })

    p.then(result => {
      console.log(result)
    }).catch(error => {
      console.log(error.message)
    })
  }

  static test3() {
    const p1 = Promise.resolve(1) // new Promise(resolve => resolve(1))
    const p2 = Promise.resolve(2)
    const p3 = Promise.resolve(3)
    // const p3 = Promise.reject(new Error('3'))

    // 有reject时只会打印3,正常是数组[1, 2, 3]
    Promise.all([p1, p2, p3]).then(resultArr => {
      console.log(resultArr)
    }, error => {
      console.log(error.message)
    })
  }

  static test4() {
    const timePromise = function (delay, id, isReject) {
      return new Promise((resolve, reject) => {
        setTimeout(function () {
          if (isReject) {
            reject(new Error('error' + id))
          } else {
            resolve('result' + id)
          }
        }, delay)
      })
    }

    const p1 = timePromise(2000, 1)
    const p2 = timePromise(1000, 2)
    const p3 = timePromise(100, 3, true)
    const p4 = timePromise(2000, 4, true)

    console.log(Date.now())
    // 同时执行多个异步操作,所有都拿到结果后,返回结果数组。
    // 如果中间有error抛出,then不会执行,catch中拿到的是第一个被执行的reject
    Promise.all([p1, p2, p3, p4]).then(resultArr => {
      console.log(resultArr)
      console.log(Date.now())
    }).catch(error => {
      console.log(error.message)
      console.log(Date.now())
    })
  }

  static test5() {
    const timePromise = function (delay, id, isReject) {
      return new Promise((resolve, reject) => {
        setTimeout(function () {
          if (isReject) {
            reject(new Error('error' + id))
          } else {
            resolve('result' + id)
          }
        }, delay)
      })
    }

    const p1 = timePromise(2000, 1)
    const p2 = timePromise(3000, 2)
    const p3 = timePromise(10000, 3, true)
    const p4 = timePromise(2000, 4, true)

    // 无论成功失败,输出执行最快的那个
    Promise.race([p1, p2, p3, p4]).then(resultArr => {
      console.log(resultArr)
    }).catch(error => {
      console.log(error.message)
      console.log(Date.now())
    })
  }

  static test6() {
    const timePromise = function (delay, id, isReject) {
      return (resolve, reject) => {
        setTimeout(function () {
          if (isReject) {
            reject(new Error('error' + id))
          } else {
            resolve('result' + id)
          }
        }, delay)
      }
    }

    const p1 = timePromise(2000, 1)
    const p2 = timePromise(2000, 2)
    const p3 = timePromise(2000, 3, true)
    const p4 = timePromise(2000, 4)

    // 顺序执行,执行完一个再执行下一个
    new Promise(p1).then(r => {
      console.log(r)
      return new Promise(p2)
    }, error => {
      console.log(error.message())
      return new Promise((p2))
    }).then(r => {
      console.log(r)
      return new Promise(p3)
    }, error => {
      console.log(error.message)
      return new Promise(p3)
    }).then(r => {
      console.log(r)
      return new Promise(p4)
    }, error => {
      console.log(error.message)
      return new Promise(p4)
    }).then(r => {
      console.log(r)
    }, error => {
      console.log(error.message)
    })
  }

  static test7() {
    function executor (resolve, reject) {
      // resolve('my-promise')
      reject(new Error('my-promise-error'))
    }
    new MyPromise(executor).then(r => {
      console.log(r)
    }, error => {
      // 当then中写onRejected的时候,catch不会触发,因为catch对应自己的MyPromise,当中并没有任何地方调用reject方法
      console.log('error from then: ' + error)
    }).catch(error => {
      // 当then中不写onRejected的到时候,catch才会触发
      // 实际上,当then中不写onRejected的时候,源码会帮我们生成一个函数 reason => throw reason
      // 所以会被try catch捕获到触发reject
      console.log('error from catch: ' + error)
    })
  }
}

// promise 三个状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

// 正常resolve的执行顺序
// 1、先执行MyPromise构造函数,也就是走到executor执行
// 2、executor执行时,会走到例子中的resolve函数
// 3、因为resolve中设置了setTimeout,所以会优先执行then
// 4、then中构建了一个新的MyPromise,重复1的步骤
// 5、因为新的MyPromise中没有resolve,所以直接执行完毕,就是往两个cb数组中塞回调函数
// 6、此时需要执行resolve中的setTimeout的部分了,这时候就把'my-promise'传给了then中的回调,打印台就打印了
function MyPromise (executor) {
  let that = this
  that.status = PENDING
  that.value = undefined // fulfilled状态时 返回的信息
  that.reason = undefined // rejected状态时 拒绝的原因
  that.onFulfilledCallbacks = [] // 存储fulfilled状态对应的onFulfilled函数
  that.onRejectedCallbacks = [] // 存储rejected状态对应的onRejected函数

  function resolve (value) {
    if (value instanceof MyPromise) {
      return value.then(resolve, reject)
    }

    setTimeout(() => {
      // 调用resolve 回调对应onFulfilled函数
      if (that.status === PENDING) {
        // 只能由pending状态 => fulfilled状态 (避免调用多次resolve reject)
        that.status = FULFILLED
        that.value = value
        that.onFulfilledCallbacks.forEach(cb => cb(that.value))
      }
    })
  }

  function reject (reason) {
    setTimeout(() => {
      // 调用reject 回调对应onRejected函数
      if (that.status === PENDING) {
        // 只能由pending状态 => rejected状态 (避免调用多次resolve reject)
        that.status = REJECTED
        that.reason = reason
        debugger
        that.onRejectedCallbacks.forEach(cb => {
          cb(that.reason)
        })
      }
    })
  }

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

MyPromise.prototype.then = function (onFulFilled, onRejected) {
  const that = this
  onFulFilled = typeof onFulFilled === 'function' ? onFulFilled : value => value
  onRejected = typeof onRejected === 'function' ? onRejected : reason => {
    throw reason
  }

  if (that.status === PENDING) { // 等待态
    return new MyPromise((resolve, reject) => {
      that.onFulfilledCallbacks.push(value => {
        try {
          onFulFilled(value)
          // 此处略去大量分支处理
        } catch (e) {
          reject(e)
        }
      })
      that.onRejectedCallbacks.push(reason => {
        try {
          onRejected(reason)
          // 此处略去大量分支处理
        } catch (e) {
          reject(e)
        }
      })
    })
  }
}

MyPromise.prototype.catch = function (onRejected) {
  return this.then(null, onRejected)
}

export default PromiseTest

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值