带你了解 “老生常谈”的Promise的实现(三)

43 阅读2分钟

一、基础功能描述

then方法可以链式调用, then返回的是一个promise,这个promise不能是then方法本身的这个promise,因为这样会陷入死循环

要把上一个then回调的返回值(return的值,分两种情况:promise和非promise)传递给下一个then方法的回调函数。

then回调返回值是一个promise时(即: return的值),不能是then方法本身的这个promise。

•返回promise和非promise

let pro = new MPromise((res, rej)=>{
  res('成功的值')
})

pro.then(value=> {
  console.log(value)
  return 100
}).then(value=> {
  console.log(value)
  return new MPromise((resolve, reject) => {
    resolve('返回的是promise')
  })
}).then(value=> {
  console.log(value)
})

• then回调返回值是一个promise(即: return的值)是then方法本身的这个promise

 var promise = new Promise(function(resolve,reject){
  resolve(100)
})

let p1 = promise.then(function(value){
  console.log(value);
  // 此时行不通,报错 Chaining cycle detected for promise #<Promise>
  return p1
})
p1.then((value)=>{
  console.log(value)
},(err)=>{
  // 获取失败原因
  console.log(err)
})

二、 代码实现

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MPromise {
  constructor(executor){
    executor(this.resolve, this.reject)
  }
  status = PENDING

  // 成功后的值
  value = undefined
  //失败后的原因
  reason = undefined

  // 为了支持异步修改状态
  // 成功回调
  successCallback = []
  // 失败回调
  failCallback = []


  // resolve 和 reject都是箭头函数。
  // 因为在使用的过程中,直接调用,this指向的是window或者undefined,要让它指向MPromise的实例对象,所以此时应该 使用箭头函数
  resolve = (value) => { // value成功后的值
    // 状态一旦修改后不能再更改
    if(this.status != PENDING) return
    this.status = FULFILLED
    this.value = value

    // 异步:判断成功回调是否存在,如果存在调用
    // this.successCallback && this.successCallback(this.value)
    while(this.successCallback.length) this.successCallback.shift()(this.value)
  }

  reject = (reason) => { // reason失败后的原因
    // 状态一旦修改后不能再更改
    if(this.status != PENDING) return
    this.status = REJECTED
    this.reason = reason

    // 异步:判断失败回调是否存在,如果存在调用
    // this.failCallback && this.failCallback(this.reason)
    while(this.failCallback.length) this.failCallback.shift()(this.reason)
  }

  then(successCallback, failCallback) {
    let promise2 = new MPromise((resolve, reject) => {
      // 状态判断
      // 同步: 一次或者多次都直接执行
      if(this.status == FULFILLED) {
        setTimeout(()=>{ // 如果不用setTimeout,此时获取不到promise2
          // then 方法的返回值x,是一个普通值
          let x = successCallback(this.value)
          // 如果是一个普通值,直接调用resolve
          // 如果是一个promise对象,查看promise对象的返回结果,根据返回的结果,决定是调用resolve还是reject
          resolvePromise(promise2, x, resolve, reject) // 如果不用setTimeout,此时获取不到promise2
        })
      } else if(this.status == REJECTED){
        // 同步: 一次或者多次都直接执行
        failCallback(this.reason)
      } else {
        // 此时说明 状态修改是异步的,需要将成功失败的回调存储起来
        this.successCallback.push(successCallback)
        this.failCallback.push(failCallback)
      }
    });
    return promise2
  }
}

function resolvePromise(promise2, x, resolve, reject){
  // 判断 返回的promise 是否等于 then方法本身的promise,如果等于直接报错
  if(promise2 == x) {
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  if(x instanceof MPromise) {
    // 返回的是promise
    // x.then(value=> resolve(value), reason => reject(reason)) 等价于
    x.then(resolve, reject)
  } else {
    // 普通值
    resolve(x)
  }
}

三、敬请期待 —— 系列四