为了账号安全,请及时绑定邮箱和手机立即绑定

请教各位一个问题,求解答:求大佬解释下下面这段代码的执行顺序

请教各位一个问题,求解答:求大佬解释下下面这段代码的执行顺序

萧十郎 2019-10-19 09:31:32
代码如下:constp=Promise.resolve();(()=>{constimplicit_promise=newPromise(resolve=>{constpromise=newPromise(res=>res(p));promise.then(()=>{console.log('after:await');resolve();});});returnimplicit_promise;})();p.then(()=>{console.log('tick:a');}).then(()=>{console.log('tick:b');}).then(()=>{console.log('tick:c');})  这段代码在node11和浏览器中的输出顺序为:tick:atick:bafter:awaittick:c不应该先输出after:await么?
查看完整描述

2 回答

?
狐的传说

TA贡献1804条经验 获得超3个赞

constp=Promise.resolve();
(()=>{
constimplicit_promise=newPromise(resolve=>{
//SYNC1
constsync1_promise=newPromise(res=>res(p)/*ASYNC2*/);
sync1_promise.then(()=>{
/*ASYNC3*/
console.log('after:await');
resolve();
});
});
returnimplicit_promise;
})();
p.then(()=>{
//TICKA
console.log('tick:a');
}).then(()=>{
//TICKB
console.log('tick:b');
}).then(()=>{
//TICKC
console.log('tick:c');
})
几点注意:
Promise的then函数回调不会同步执行,如果Promise已经被resolve或reject,那么其回调会被放进异步队列。当Promise并没有被resolve或reject的时候,then的回调不会被放入任务队列,而是在Promise在被resolve或reject的时候才放入异步队列。
Promise的then(onFullfilled,onReject)会返回一个新的Promise,这个新的Promise会在onFullfilled或onReject别执行之后,被resolve或reject。
当使用Promise来rosolve另一个Promise的时候(res=>res(p)),会建立一个异步任务,并在异步任务里调用p.then(res)。
所以:同步任务,p是一个已经resolve的Promise。匿名函数直接调用,SYNC1执行,ASYNC2执行。ASYNC2执行并没有resolvesync1_promise(见以上第三点),而是增加了一个异步任务(异步1),在异步任务里将执行p.then(res)。于是,SYNC1中的sync1_promise并没有被resolve,ASYNC3也并不会被放入异步队列。接下来,由于p已经resolve,TICKA被放入异步队列(异步2)。但是,其返回Promise由于TICKA并没有被调用(还在异步队列里),并没有被resolve,于是TICKB与TICKC均不会被放入异步队列。
异步1:执行p.then(res),p已经resolve,所以res被放入异步队列(异步3)异步2:执行TICKA,输出"tick:a"。同时,rosolvep.then(TICKA)返回的Promise,TICKB被放入队列(异步4)异步3:执行res(),resolve掉SYNC1中的sync1_promise,于是在它的then里注册的ASYNC3被放入队列(异步5)异步4:执行TICKB,输出"tick:b"。同时,rosolvep.then(TICKA).then(TICKB)返回的Promise,TICKC被放入队列(异步6)异步5:执行ASYNC3,输出"after:await"。resolveimplicit_promise。异步6:执行TICKC,输出"tick:c"
                            
查看完整回答
反对 回复 2019-10-19
?
慕沐林林

TA贡献2016条经验 获得超9个赞

js是单线程,而promise是异步的,总是后执行,异步里套异步,也是先把同层级的异步任务跑完再去跑下一层级异步任务。造成这个的原因可以看下eventLoop;
这是别人的例子,可以看看想想。
setTimeout(function(){
console.log(1);
setTimeout(function(){
console.log(2);
},0);
},0);
setTimeout(function(){
console.log(3);
setTimeout(function(){
console.log(4);
},0);
},0);
结果打印1324,而不是1234。
链接描述JavaScript运行机制详解:再谈EventLoop
                            
查看完整回答
反对 回复 2019-10-19
  • 2 回答
  • 0 关注
  • 289 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信