Promise - (六)关于then参数回调函数的缓存位置理解

题目来源于:【JS】因两道Promise执行题让我产生自我怀疑,从零手写Promise加深原理理解 - 听风是风 - 博客园 (cnblogs.com)

const fn = (s) => {
  new Promise((resolve, reject)=>{
    if(typeof s === 'number') {
      resolve()
    } else {
      reject()
    }
  })
  .then(res => {
    console.log('数字');
  })
  .catch(err => {
    console.log('字符串');
  })
}

fn('1')
fn(1)

此题结果为

Promise - (六)关于then参数回调函数的缓存位置理解_第1张图片
①首先fn('1')执行中,new Promise会同步返回一个rejected态的promise1对象,
②之后promise1对象会继续同步调用then方法,由于是promise1是失败态的,所以会将then方法的第二个参数回调(onReject回调)加入异步微任务队列
【ps:当未传onReject回调给then方法时,then方法内部会生成一个默认的onReject回调,即异常穿透回调 err => {throw err}】
③ 此时promise1.then执行结果会同步返回一个pending态的promise2对象,promise2对象的状态改变依赖于被加入异步微任务队列中onReject回调的执行
④ promise2对象继续同步调用catch方法,由于promise2对象是pending态的,所以catch方法的参数回调函数不会被加入异步微任务队列,而是缓存进了promise2对象的内部属性中,等待promise2对象的状态从pending态变为其他态时,catch的参数回调函数才会被加入异步微任务队列。
⑤ 此时fn('1')同步执行完成,下面开始执行fn(1)
⑥同理fn(1)中new Promise会同步地返回一个成功fulfilled态的promise3对象
⑦ promise3对象同步调用then方法,并将then方法的onFulfill回调参数加入异步微任务队列,并返回一个pending态的promise4对象
【ps.此时异步微任务队列中已有两个回调函数,依次是promise1对象加入的 err=>{throw err},和promise3加入的 res => console.log('参数是一个number')】
⑧ promise4对象继续同步调用catch方法,由于promise4对象是pending的,所以将catch的回调函数参数缓存进自身内部属性中
⑨ 至此fn(1)同步执行完成,JS主线程检查同步代码都执行完了,则开始事件循环,去异步任务队列中取回调到执行栈执行,由于异步宏任务队列是空的,所以直接从异步微任务队列中取出第一个回调函数,即promise1对象加入的 err=>{throw err}
⑩ promise1对象加入的 err=>{throw err}执行,就会导致promise2对象的状态变为rejected,进而导致promise2对象将缓存在内部属性中的失败回调err => console.log('参数是一个字符串') 加入异步微任务队列中。
【ps.此时异步微任务队列出了一个,进了一个,剩下的依次是:promise3加入的 res => console.log('参数是一个number') 和 promise2加入的err => console.log('参数是一个字符串') 】
之后就好理解了,JS主线程继续依次取出异步微任务队列中的回调执行,所以先打印了number,再打印了”字符串“

你可能感兴趣的:(Promise,promise,then)