Promise的then方法中的回调函数和setTimeout执行顺序问题

  setTimeout(function(){
        console.log('D');
    },0)

    var promise = new Promise(function(resolve, reject){
        console.log('A');
        resolve('C');
    })

    console.log('B');
    
      promise.then(function(value){
        console.log(value)
    });
    
    这段代码AB先打印我没问题,就是不理解为什么是C先于D打印,按理说应该是setTimeout先把回调放进任务队列里面等待执行吧
阅读 4.1k
4 个回答

这里涉及到异步的宏任务和微任务,setTimeout是宏任务,Promise整体是微任务,主线程执行完了之后先从微任务栈里面获取微任务执行,没有微任务了,就去宏任务栈里面获取宏任务执行,所以在一个循环内,微任务是比宏任务先执行的,所以先打印C再打印D

因为有俩个队列.

一个是 microtask 队列, 一个 macrotask 队列.

promise 是放入 microtask 队列的, 而 setTimeout 放入 macrotask 队列.

先处理 microtask 队列, microtask 队列每次处理直到队列为空, 接下来处理 macrotask 队列, macrotask 每次只处理的队列里的第一个任务, 当任务处理完后, 又会进入到 microtask 队列的处理. 如此反复.

这个很好理解,根本在于明确理解异步问题。

首先关于setTimeout你的理解没错,是一个队列执行,这里类似于setTimeout的还有很多,比如node中的:
setImmediate, process.nextTick等,都是类似机制。
这些函数都是延时执行,顾名思义就是要放进队列排队的,哪怕设置了延时0.

但是 Promise是什么呢
简单说,不过是 一种 异步编程的解决方案,说白了是改变之前 回调函数写法的 问题。Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。而这个存储的队列是promsie本身维护的自己的队列,千万不要和setTimeout的系统事件调度队列混淆。

针对你的这个问题,你这个promise没有异步,所以promsie的状态马上就变成了 resolve的,所以呢,通过then注册的回调函数马上就会调用。基本是就是同步执行而已。当然比setTimeout先执行。

setTimeout(function(){console.log(4)},0); 
new Promise(function(resolve){ 
    console.log(1) 
    setTimeout(()=>{console.log('x');resolve();},100) 
    console.log(2) })
.then(function(){ console.log(5) }).then(()=>{for(let i=0;i<1000;i++){}console.log(6)});
 console.log(3);
setTimeout(function(){console.log(4)},100); 
new Promise(function(resolve){ 
    console.log(1) 
    setTimeout(()=>{console.log('x');resolve();},0) 
    console.log(2) })
.then(function(){ console.log(5) }).then(()=>{for(let i=0;i<1000;i++){}console.log(6)});
 console.log(3);

then在resolve后立即执行,所以说then和settimeout的执行顺序其实是resolve和setTimeout的先后顺序作比较,不知道这样理解对不对?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题