zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Promise - (五)then方法参数回调函数加入异步微任务队列的时机

方法队列异步队列 函数 参数 任务 加入
2023-09-14 09:13:41 时间

先看一个例子

Promise.resolve().then(()=>{
    setTimeout(()=>{
        console.log(1)
    })
}).then(()=>{
    console.log(2)
})

思考一个问题1

在JS事件循环机制触发前,即JS同步代码执行阶段,上面两个then都会执行吗?还是只执行第一个then?

答:两个then都会执行,因为then方法调用是同步的

再思考一个问题2

在JS事件循环机制触发前,即JS同步代码执行阶段,上面两个then都有返回值吗?是什么?

答:两个then执行后都会有返回值,且都是状态为pending的promise对象

再思考一个问题3

在JS事件循环机制触发前,即JS同步代码执行阶段,上面两个then执行结束后,对应的在执行栈中的函数执行上下文会被出栈销毁吗?

答:函数调用,则会创建函数执行上下文进入执行栈,函数调用结束,则对应的函数执行上下文出栈销毁。

终极一问4

then的执行上下文被销毁了,then指定的回调函数去哪了?也被销毁了吗?

答:then被销毁前,会对then指定的回调函数做一些处理:

若调用then的promise对象状态已经不是pending了,则直接将回调函数推入异步微任务队列中存储

若调用then的promise对象状态还是pending,则会将回调函数交给调用者promise对象缓存,当promise对象状态被异步修改后,再去将回调函数推入异步任务队列中存储。

补充一问5

在then方法调用前一刻,调用它的promise对象的状态是啥?一定是非pending吗,或一定是pending吗?

我们需要搞清楚,promise对象的状态会在哪里被修改

答:不考虑Promise内部实现,仅考虑Promise使用,则只有一个地方可以修改promise对象的状态,那就是new Promise(excutor)的excutor执行器函数中,在excutor函数中调用resolve或reject方法修改promise对象的状态。

promise对象状态的修改有几种情况?

两种,同步修改或异步修改

在excutor中同步调用resolve或reject会导致,then方法调用前一刻,promise对象的状态就已经是非pending了

在excutor中异步调用resolve或reject会导致,then方法调用结束后,promise对象的状态依旧是pending的

所以我们在重写then方法时,需要考虑promise对象的状态pending,非pending都有可能