javascript事件循环到底是先执行宏任务还是先执行微任务?

网上看了很多关于js事件循环的文章
有的说是先执行微任务,有的说是先执行宏任务,
大部分都会说 script脚本会被当做宏任务先执行,我理解 script脚本 本身可以算宏任务吗?
宏任务和微任务理论上是只有异步任务才有,script脚本 是不是只能算是同步任务,所以先执行了?
请求懂的大佬解答我的疑惑,感激不尽。

阅读 6k
3 个回答

借用掘金上一篇文章的图:
image.png
简单来说,执行一段代码时,整段代码会作为宏任务进入主线程执行,接下来会有3种情况:

  • 同步代码,直接执行
  • 碰到setTimeout,分发到宏任务队列
  • 碰到Promise.then,分发到微任务队列
console.log(1); // 直接执行

setTimeout(function() {
    console.log(2); // 进入宏任务队列
})

new Promise(function(resolve) {
    console.log(3); //直接执行
    resolve()
}).then(function() {
    console.log(4); // 进入微任务队列
})

console.log(5); // 直接执行

在一次事件循环中,会先执行宏任务(主线程)再执行微任务(then)。
都执行完后则进入下一次事件循环,再从宏任务开始执行(setTimeout)。

所以在整段代码中,setTimeout是在then之后执行的,因为他俩不在同一次事件循环中。
所以,你问题的关键是在于你指的是一次事件循环中还是一整段代码中。

事件循环中,宏任务先执行
整段代码中,异步的微任务先执行

执行一下这段代码,看看与你所想的一不一样。

从一道题浅说 JavaScript 的事件循环
可以看看这篇文章,我觉得讲的蛮好的。
script 脚本是异步任务,他执行是因为当前的微任务队列是空,而宏任务队列只有script这个任务,在清空微任务队列(空,啥也没执行)后,然后开始执行script里面的代码,然后script里面的异步代码又分为宏任务和微任务,微任务放到微任务队列,宏任务放到宏任务队列,执行完script中的代码后,然后又开始清空微任务队列和宏任务队列...就这样一直执行下去,直到清空微任务队列和宏任务队列

首先,整体的script(作为第一个宏任务)开始执行的时候,会把所有代码分为同步任务、异步任务两部分
同步任务会直接进入主线程依次执行
异步任务会再分为宏任务和微任务
宏任务进入到Event Table中,并在里面注册回调函数,每当指定的事件完成时,Event Table会将这个函数移到Event Queue中
微任务也会进入到另一个Event Table中,并在里面注册回调函数,每当指定的事件完成时,Event Table会将这个函数移到Event Queue中
当主线程内的任务执行完毕,主线程为空时,会检查微任务的Event Queue,如果有任务,就全部执行,如果没有就执行下一个宏任务
上述过程会不断重复,这就是Event Loop,比较完整的事件循环。
js一次只能执行一个宏任务,一次可以执行多个微任务。
所以个人理解,还是先执行宏任务,再执行微任务。

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