PromiseA+实现不过如此

683 阅读11分钟

写在最前

promiseA+实现其实很简单,就是里面回调函数的设计有点点绕,相信看完本文,一定会有所收获!本文主要是参考coderwhy大神的授课加上自己的理解。

Promise作用

Promise的出现解决了什么问题呢,解决的就是我们发送网络请求时,我们需要自己设计回调函数,而每个人所设计的回调函数方式不同,使我们使用异步函数执行回调时更加的规范。

  • Promise是一个类,可以翻译成 承诺、许诺 、期约
  • 当我们需要给予调用者一个承诺:待会儿我会给你回调数据时,就可以创建一个Promise的对象;
  • 在通过new创建Promise对象时,我们需要传入一个回调函数,我们称之为executor
    • 这个回调函数会被立即执行,并且给传入另外两个回调函数resolvereject
    • 当我们调用resolve回调函数时,会执行Promise对象的then方法传入的回调函数;
    • 当我们调用reject回调函数时,会执行Promise对象的catch方法传入的回调函数;

Promise的结构设计

//定义常量,表示promise的三种不同状态
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class MyPromise {
//构造函数所传入的executor就是我们平时调用Promise传入的函数
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined

    const resolve = (value) => {
//我们知道promise状态一经改变,便不能再次改变状态
      if (this.status === PROMISE_STATUS_PENDING) {
        this.status = PROMISE_STATUS_FULFILLED
        this.value = value
        console.log('resolve被调用')
      }
    }

    const reject = (reason) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        this.status = PROMISE_STATUS_REJECTED
        this.reason = reason
        console.log('reject被调用')
      }
    }
    //这个executor会被直接执行,并且传入我们定义的resolve函数和reject函数
    executor(resolve, reject)
  }
}

//测试代码
//执行结果:
//状态pending
//resolve被调用
const promise = new MyPromise((resolve, reject) => {
  console.log('状态pending')
  resolve(1111)
  reject(2222)
})

Promise的then方法

实现then方法的第一步

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

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

    const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        this.status = PROMISE_STATUS_FULFILLED
        //queueMicrotask微任务
        queueMicrotask(() => {
        //只能开启一个微任务才能拿到this.onFulfilled
        //then方法是同步被调用,如果不开启微任务,那么this.onFulfilled将会为undefined
          this.value = value
          this.onFulfilled(this.value)
        })
      }
    }

    const reject = (reason) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        this.status = PROMISE_STATUS_REJECTED
        queueMicrotask(() => {
        //只能开启一个微任务才能拿到this.onRejected
        //then方法是同步被调用,如果不开启微任务,那么this.onRejected将会为undefined
          this.reason = reason
          this.onRejected(this.reason)
        })
      }
    }

    executor(resolve, reject)
  }
//then方法是被我们同步调用的,比如
//Promise.resolve('aaa').then((res)=>{log(res),(err)=>{log(err)})
//那么我们在then中传递的两个函数是怎么在Promise resolve/reject之后被调用呢
//答案就是开启一个微任务
  then(onFulfilled, onRejected) {
    this.onFulfilled = onFulfilled
    this.onRejected = onRejected
  }
}

const promise = new HYPromise((resolve, reject) => {
  console.log('状态pending')
  reject(2222)
  resolve(1111)
})

// 测试代码
//执行结果:
//状态pending
//err: 2222
promise.then(
  (res) => {
    console.log('res1:', res)
  },
  (err) => {
    console.log('err:', err)
  }
)

优化then方法

问题1:then方法是可以被多次调用的

promise.then(res => {
  console.log("res1:", res)
}, err => {
  console.log("err:", err)
})

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

问题2:Promise状态确定之后也是可以调用then方法的

const promise = new Promise((resolve, reject) => {
   resolve("aaaaa")
 })
// 在确定Promise状态之后, 再次调用then
setTimeout(() => {
  promise.then(res => {
    console.log("res:", res)
  }, err => {
    console.log("err3:", err)
  })
}, 1000)
//执行结果:res:aaaaa

所以我们要对上一份代码进行优化

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    //这里我们使用两个数组保存传入的函数(对应then方法多次被调用)
    this.onFulfilledFns = []
    this.onRejectedFns = []

    const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        // 添加微任务
        queueMicrotask(() => {  
        //为什么要加此判断呢?
        //这是为了Promise状态改变之后,防止执行另一状态对应的回调函数
        //因为我们将Promise的状态改变放在了微任务里面
          if (this.status !== PROMISE_STATUS_PENDING) return
        //为什么要把状态的改变提在里面来呢?
        //因为我们为了解决问题2,在下面添加回调函数时进行了判断,
        //如果在外面改变状态,那么后续本来要添加的回调函数将直接被执行
          this.status = PROMISE_STATUS_FULFILLED
          this.value = value
          //取出函数依次回调
          this.onFulfilledFns.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
          this.onRejectedFns.forEach(fn => {
            fn(this.reason)
          })
        })
      }
    }

    executor(resolve, reject)
  }

  then(onFulfilled, onRejected) {
    // 1.如果在then调用的时候, 状态已经确定下来,直接执行
    if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
      onFulfilled(this.value)
    }
    if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
      onRejected(this.reason)
    }

    // 2.将成功回调和失败的回调放到数组中
    if (this.status === PROMISE_STATUS_PENDING) {
      this.onFulfilledFns.push(onFulfilled)
      this.onRejectedFns.push(onRejected)
    }
  }
}

const promise = new mYPromise((resolve, reject) => {
  console.log("状态pending")
  resolve(1111) // resolved/fulfilled
  reject(2222)
})

//测试代码:
// 调用then方法多次调用
promise.then(res => {
  console.log("res1:", res)
}, err => {
  console.log("err:", err)
})

promise.then(res => {
  console.log("res2:", res)
}, err => {
  console.log("err2:", err)
})
// 在确定Promise状态之后, 再次调用then
setTimeout(() => {
  promise.then(res => {
    console.log("res3:", res)
  }, err => {
    console.log("err3:", err)
  })
}, 1000)
//执行结果:
//状态pending
//res1: 1111
//res2: 1111
//res3: 1111

再次优化then方法

问题:返回的promise是可以进行链式调用的:

  promise.then(
    (res) => {
      console.log('res1:', res)
      return 'aaaa'
      // throw new Error("err message")
    },
    (err) => {
      console.log('err1:', err)
      return 'bbbbb'
      // throw new Error("err message")
    }
  )
  .then(
    (res) => {
      console.log('res2:', res)
    },
    (err) => {
      console.log('err2:', err)
    }
  )

我们怎么使我们的promise能够链式调用呢?那么就要对then方法的返回值做文章了,上一份代码then方法是没有返回任何东西的,试想一下,只要使我们的then方法继续返回promise,那不就解决了吗!

注意then方法返回prmoise,那么这个promise什么时候resolve,什么时候reject呢?
then方法传入的回调函数是可以有返回值的,resolve这个值;如果then方法传入的回调函数执行过程出错就reject

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

// 工具函数
function execFunctionWithCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value)
    resolve(result)
  } catch (err) {
    reject(err)
  }
}

class MyPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilledFns = []
    this.onRejectedFns = []

    const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        // 添加微任务
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDING) return
          this.status = PROMISE_STATUS_FULFILLED
          this.value = value
          this.onFulfilledFns.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
          this.onRejectedFns.forEach((fn) => {
            fn(this.reason)
          })
        })
      }
    }
    //如果在执行executor过程中出现错误,调用reject
    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }

  then(onFulfilled, onRejected) {
  //返回值直接在new一个MyPromise,直接解决问题
    return new MyPromise((resolve, reject) => {
      if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
      //如果传入函数执行过程中出错,调用reject
      //否者对resolve函数执行结果
        // try {
        //   const value = onFulfilled(this.value)
        //   resolve(value)
        // } catch(err) {
        //   reject(err)
        // }
        //有重复逻辑,进行一个封装
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
        // try {
        //   const reason = onRejected(this.reason)
        //   resolve(reason)
        // } catch(err) {
        //   reject(err)
        // }
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
      }
      if (this.status === PROMISE_STATUS_PENDING) {
        this.onFulfilledFns.push(() => {
          // try {
          //   const value = onFulfilled(this.value)
          //   resolve(value)
          // } catch(err) {
          //   reject(err)
          // }
          execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
        })
        this.onRejectedFns.push(() => {
          // try {
          //   const reason = onRejected(this.reason)
          //   resolve(reason)
          // } catch(err) {
          //   reject(err)
          // }
          execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
        })
      }
    })
  }
}

const promise = new MyPromise((resolve, reject) => {
  console.log('状态pending')
  reject(2222)
})

// 调用then方法多次调用
promise
  .then(
    (res) => {
      console.log('res1:', res)
      return 'aaaa'
      // throw new Error("err message")
    },
    (err) => {
      console.log('err1:', err)
      return 'bbbbb'
      // throw new Error("err message")
    }
  )
  .then(
    (res) => {
      console.log('res2:', res)
    },
    (err) => {
      console.log('err2:', err)
    }
  )
//执行结果:
//状态pending
//err1: 2222
//res2: bbbbb

catch方法

catch(onRejected) {
    return this.then(undefined, onRejected)
  }
  //catch方法如此之简单,但是仅仅这样做会出现一个问题
  //试想如果是以下代码:
const promise = new MyPromise((resolve, reject) => {
  console.log('状态pending')
  reject(2222)
})
promise
  .then((res) => {
    console.log('res:', res)
  })
  .catch((err) => {
    console.log('err:', err)
  })
//promise的then中并未传入第二个函数,那么执行结果仅仅是:状态pending
//因为我们then方法中返回的promise会在传入执行函数执行之后调用resolve/reject
//如果不给then传入第二个参数,那么then返回的promise将会一直处于pendding状态
//自然不会调用后续的catch传入的函数

为解决上述问题,我们可以再修改一下then

  then(onFulfilled, onRejected) {
  //仅仅设置一个onRejected默认值,将上一个promise reject的错误抛出即可
    const defaultOnRejected = (err) => {
      throw err
    }
    onRejected = onRejected || defaultOnRejected

    return new MyPromise((resolve, reject) => {

      if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
      }

      if (this.status === PROMISE_STATUS_PENDING) {
        if (onFulfilled)
          this.onFulfilledFns.push(() => {
            execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
          })
        if (onRejected)
          this.onRejectedFns.push(() => {
            execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
          })
      }
    })
  }

此时出现我们想要的结果

//测试代码
const promise = new MyPromise((resolve, reject) => {
  console.log('状态pending')
  reject(2222)
})
promise
  .then((res) => {
    console.log('res:', res)
  })
  .catch((err) => {
    console.log('err:', err)
  })
  //执行结果:
  //状态pending
  //err: 2222

还有一个类似的问题,由于catch方法内部调用then,但是没有传入onFulfilled,那么在catch方法后续继续链式调用也会得不到结果

const promise = new MyPromise((resolve, reject) => {
  console.log('状态pending')
  resolve(1111)
})

// 调用then方法多次调用
promise
  .then((res) => {
    console.log('res:', res)
  })
  .catch((err) => {
    console.log('err:', err)
    return 'aaa'
  })
  .then((res2) => {
    console.log(res2, 'res')
  })
//执行结果:
//状态pending
//res: 1111

这个时候还是老样子,只给onFulfilled设置一个默认值即可

const defaultOnFulfilled = value => { return value }
onFulfilled = onFulfilled || defaultOnFulfilled

finally

  finally(onFinally) {
    this.then(onFinally
    ,onFinally)
  }
  //如此简单

Promise类上的静态方法

resolve、reject

我们会为了方便直接拿到一个promise,常常会这样使用Promise.resolve('xiaozhao').then((res)=>{log(res)})

//没错,就是这么简单明了
  static resolve(value) {
    return new HYPromise((resolve) => resolve(value))
  }

  static reject(reason) {
    return new HYPromise((resolve, reject) => reject(reason))
  }
  
  //测试代码
  MyPromise.resolve("Hello World").then(res => {
  console.log("res:", res)
})

  MyPromise.reject("Error Message").catch(err => {
  console.log("err:", err)
  //执行结果:
  //res: Hello World
  //err: Error Message
})

all

all方法返回一个promise,并且接受一个数组(里面存放promise,也可以是普通值)
当数组里面的promise都被reslove以后,all返回的promise resolve,否者reject

  static all(promises) {
    return new MyPromise((reslove, reject) => {
      if (typeof promises[Symbol.iterator] !== 'function') {
        reject('err')
      }
      if (promises.length === 0) {
        reslove([])
      }
      const value = []
      promises.forEach((promise) => {
        //这里有可能传的是别的,不是promise,可能是基本数据类型,可以包裹一下
        //这里用原生Promise包裹,因为我们实现的MyPromise没有考虑resolve promise
        //当然我们也可以做,在resolve里面判断一下是否是promise
        //如果是就promise.then(resolve,reject)
        Promise.resolve(promise).then(
          (res) => {
            value.push(res)
            if (value.length === promises.length) {
              reslove(value)
            }
          },
          (err) => {
            reject(err)
          }
        )
      })
    })
    //测试代码
const p1 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject(1111)
  }, 3000)
})
const p2 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject(2222)
  }, 2000)
})
const p3 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject(3333)
  }, 3000)
})

MyPromise
  .all([p1, p2, p3])
  .then((res) => {
    console.log('res:', res)
  })
  .catch((err) => {
    console.log('err:', err)
  })
  //执行结果
  //err: 2222

allSettled

返回值和参数都和all一样,返回的promise一定是fulfilled状态
原理:等到传入的所有promise都有结果,并且一定执行resolve

  static allSettled(promises) {
    return new MyPromise((resolve) => {
      const results = []
      promises.forEach((promise) => {
        promise.then(
          (res) => {
            results.push({ status: PROMISE_STATUS_FULFILLED, value: res })
            if (results.length === promises.length) {
              resolve(results)
            }
          },
          (err) => {
            results.push({ status: PROMISE_STATUS_REJECTED, value: err })
            if (results.length === promises.length) {
              resolve(results)
            }
          }
        )
      })
    })
  }

race/any

  static race(promises) {
  //只要有结果,立即resolve/reject
    return new MyPromise((resolve, reject) => {
      promises.forEach((promise) => {
        // promise.then(res => {
        //   resolve(res)
        // }, err => {
        //   reject(err)
        // })
        // console.log(resolve.)
        promise.then(resolve, reject)
      })
    })
  }

  static any(promises) {
    // resolve必须等到有一个成功的结果
    // reject所有的都失败才执行reject
    const reasons = []
    return new MyPromise((resolve, reject) => {
      promises.forEach((promise) => {
        promise.then(resolve, (err) => {
          reasons.push(err)
          if (reasons.length === promises.length) {
            reject(new AggregateError(reasons))
          }
        })
      })
    })
  }

所有代码

// https://promisesaplus.com/
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

// 工具函数
function execFunctionWithCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value)
    resolve(result)
  } catch (err) {
    reject(err)
  }
}

class dyPromise {
  constructor(executor) {
    this.status = PROMISE_STATUS_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilledFns = []
    this.onRejectedFns = []

    const resolve = (value) => {
      if (this.status === PROMISE_STATUS_PENDING) {
        // 添加微任务
        queueMicrotask(() => {
          if (this.status !== PROMISE_STATUS_PENDING) return
          this.status = PROMISE_STATUS_FULFILLED
          this.value = value
          this.onFulfilledFns.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
          this.onRejectedFns.forEach((fn) => {
            fn(this.reason)
          })
        })
      }
    }

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

  then(onFulfilled, onRejected) {
    const defaultOnRejected = (err) => {
      throw err
    }
    onRejected = onRejected || defaultOnRejected

    const defaultOnFulfilled = (value) => {
      return value
    }
    onFulfilled = onFulfilled || defaultOnFulfilled

    return new dyPromise((resolve, reject) => {
      // 1.如果在then调用的时候, 状态已经确定下来
      if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
      }

      // 2.将成功回调和失败的回调放到数组中
      if (this.status === PROMISE_STATUS_PENDING) {
        if (onFulfilled)
          this.onFulfilledFns.push(() => {
            execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
          })
        if (onRejected)
          this.onRejectedFns.push(() => {
            execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
          })
      }
    })
  }

  catch(onRejected) {
    return this.then(undefined, onRejected)
  }

  finally(onFinally) {
    this.then(
      () => {
        onFinally()
      },
      () => {
        onFinally()
      }
    )
  }

  static resolve(value) {
    return new dyPromise((resolve) => resolve(value))
  }

  static reject(reason) {
    return new dyPromise((resolve, reject) => reject(reason))
  }

  static all(promises) {
    return new dyPromise((reslove, reject) => {
      if (typeof promises[Symbol.iterator] !== 'function') {
        reject('err')
      }
      if (promises.length === 0) {
        reslove([])
      }
      const value = []
      promises.forEach((promise) => {
        //这里有可能传的是别的,不是promise
        Promise.resolve(promise).then(
          (res) => {
            value.push(res)
            if (value.length === promises.length) {
              reslove(value)
            }
          },
          (err) => {
            reject(err)
          }
        )
      })
    })
    // 问题关键: 什么时候要执行resolve, 什么时候要执行reject
    return new dyPromise((resolve, reject) => {
      const 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 dyPromise((resolve) => {
      const results = []
      promises.forEach((promise) => {
        promise.then(
          (res) => {
            results.push({ status: PROMISE_STATUS_FULFILLED, value: res })
            if (results.length === promises.length) {
              resolve(results)
            }
          },
          (err) => {
            results.push({ status: PROMISE_STATUS_REJECTED, value: err })
            if (results.length === promises.length) {
              resolve(results)
            }
          }
        )
      })
    })
  }

  static race(promises) {
    return new dyPromise((resolve, reject) => {
      promises.forEach((promise) => {
        // promise.then(res => {
        //   resolve(res)
        // }, err => {
        //   reject(err)
        // })
        // console.log(resolve.)
        promise.then(resolve, reject)
      })
    })
  }

  static any(promises) {
    // resolve必须等到有一个成功的结果
    // reject所有的都失败才执行reject
    const reasons = []
    return new dyPromise((resolve, reject) => {
      promises.forEach((promise) => {
        promise.then(resolve, (err) => {
          reasons.push(err)
          if (reasons.length === promises.length) {
            reject(new AggregateError(reasons))
          }
        })
      })
    })
  }
}

写在最后

一道面试题,看到很多大佬都在讨论

Promise.resolve().then(() => {
  console.log(0);
  return Promise.resolve(4)
}).then((res) => {
  console.log(res)
})

Promise.resolve().then(() => {
  console.log(1);
}).then(() => {
  console.log(2);
}).then(() => {
  console.log(3);
}).then(() => {
  console.log(5);
}).then(() =>{
  console.log(6);
})
// 0
// 1
// 2
// 3
// 4
// 5
// 6

为什么会有这样的执行结果呢,是因为js引擎做了优化,对return Promise.resolve(4)加了两次微任务,为什么会做这样的优化呢,请看我娓娓道来

Promise.resolve()
  .then(() => {
    console.log(0)
    return 4

  })
  .then((res) => {
    console.log(res)
  })
Promise.resolve()
  .then(() => {
    console.log(1)
  })
  .then(() => {
    console.log(2)
  })
  .then(() => {
    console.log(3)
  })
  .then(() => {
    console.log(5)
  })
  .then(() => {
    console.log(6)
  })
// 0
// 1
// 4
// 2
// 3
// 5
// 6


Promise.resolve()
  .then(() => {
    console.log(0)
    //return thenable的值
    return {
      then: function (resolve) {
        // 大量的计算
        resolve(4)
      }
    }

  })
  .then((res) => {
    console.log(res)
  })
Promise.resolve()
  .then(() => {
    console.log(1)
  })
  .then(() => {
    console.log(2)
  })
  .then(() => {
    console.log(3)
  })
  .then(() => {
    console.log(5)
  })
  .then(() => {
    console.log(6)
  })
// 0
// 1
// 2
// 4
// 3
// 5
// 6

可见return一个thenable的对象,会加一次微任务,因为thenable函数中的有可能存在耗时操作(比如有大量的计算),那么就有可能阻塞后续的微任务,所以加一次微任务
你可能有疑问,加一次微任务,虽然不会阻塞后一次微任务,但是如果后一次微任务中又添加微任务(就像这道面试题),那不是又阻塞住了?
事实上这是一种特殊情况,我们现实中的代码是不会接连着微任务中加微任务的
所以就可以理解return一个thenable的对象,会加一次微任务;那么我们就知道then中返回特殊值会加一次微任务,那么返回一个promise算是特殊值(加一次微任务),而promise本身加一次微任务,所以一共加两次微任务,不得不感叹v8的强大希望对你有帮助