代码如下: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 回答
慕娘9325324
TA贡献1783条经验 获得超4个赞
constp=Promise.resolve();(()=>{constimplicit_promise=newPromise(resolve=>{//SYNC1constsync1_promise=newPromise(res=>res(p)/*ASYNC2*/);sync1_promise.then(()=>{/*ASYNC3*/console.log('after:await');resolve();});});returnimplicit_promise;})();p.then(()=>{//TICKAconsole.log('tick:a');}).then(()=>{//TICKBconsole.log('tick:b');}).then(()=>{//TICKCconsole.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"
当年话下
TA贡献1890条经验 获得超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
添加回答
举报
0/150
提交
取消