先运行下面的一段代码:segmentfault
console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); console.log('script end'); //"script start" //"script end" //"setTimeout"
这里一看,setTimeout的延时为 0 ,那么是否是程序执行到这里以后就当即执行setTimeout里面的函数呢?其实不是的.
这是由于 JavaScript 主线程拥有一个 执行栈 以及一个 任务队列,主线程会依次执行代码,当遇到函数时,会先将函数 入栈,函数运行完毕后再将该函数 出栈,直到全部代码执行完毕。promise
那么遇到 WebAPI(例如:setTimeout
, AJAX
)这些函数时,这些函数会当即返回一个值,从而让主线程不会在此处阻塞。而真正的异步操做会由浏览器执行,浏览器会在这些任务完成后,将事先定义的回调函数推入主线程的 任务队列 中。浏览器
而主线程则会在 清空当前执行栈后,按照先入先出的顺序读取任务队列里面的任务。异步
那么咱们来看一下上面程序的执行顺序:函数
// 1. 开始执行 console.log('script start'); // 2. 打印字符串 "script start" setTimeout( function() { // 5. 浏览器在 0ms 以后将该函数推入任务队列 // 而到第5步时才会被主线程执行 console.log('setTimeout'); // 6. 打印字符串 "setTimeout" }, 0 ); // 3. 调用 setTimeout 函数,并定义其完成后执行的回调函数 console.log('script end'); // 4. 打印字符串 "script end" // 5. 主线程执行栈清空,开始读取 任务队列 中的任务
以上就是浏览器的异步任务的执行机制,核心点为:oop
Macrotask 和 microtask 都是属于上述的异步任务中的一种,咱们先看一下他们分别是哪些 API :线程
macrotasks: setTimeout, setInterval, setImmediate, I/O, UI renderingcode
microtasks: process.nextTick, Promises, Object.observe(废弃), MutationObserverserver
setTimeout 的 macrotask ,和 Promise 的 microtask 有什么不一样呢? 咱们经过下面的代码来展示他们的不一样点:对象
console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); Promise.resolve().then(function() { console.log('promise1'); }).then(function() { console.log('promise2'); }); console.log('script end'); //"script start" //"script end" //"promise1" //"promise2" //"setTimeout"
在这里,setTimeout的延时为0,而Promise.resolve()也是返回一个被resolve了promise对象,即这里的then方法中的函数也是至关于异步的当即执行任务
这里的运行结果是Promise的当即返回的异步任务会优先于setTimeout延时为0的任务执行。
缘由是任务队列分为 macrotasks 和 microtasks,而Promise中的then方法的函数会被推入 microtasks 队列,而setTimeout的任务会被推入 macrotasks 队列。在每一次事件循环中,macrotask 只会提取一个执行,而 microtask 会一直提取,直到 microtasks 队列清空。
注:通常状况下,macrotask queues 咱们会直接称为 task queues,只有 microtask queues 才会特别指明。
那么也就是说若是个人某个 microtask 任务又推入了一个任务进入 microtasks 队列,那么在主线程完成该任务以后,仍然会继续运行 microtasks 任务直到任务队列耗尽。
而事件循环每次只会入栈一个 macrotask ,主线程执行完该任务后又会先检查 microtasks 队列并完成里面的全部任务后再执行 macrotask
参考:清蒸不是水煮 的文章
阮一峰 - JavaScript 运行机制详解:再谈Event Loop
Philip Roberts - Help,I’m stuck in an event loop