JS时间循环宏任务微任务 讲解+面试题
什么是事件循环?
事实上我把事件循环理解成我们编写的JavaScript和浏览器或者Node之间的一个桥梁
浏览器的事件循环是一个我们编写的JavaScript代码和浏览器API调用(setTimeout/AJAX/监听事件等)的一个桥梁, 桥梁之间他们通过回调函数进行沟通。
Node的事件循环是一个我们编写的JavaScript代码和系统调用(file system、network等)之间的一个桥梁, 桥梁 之间他们通过回调函数进行沟通的
JS代码执行流程

- 定义变量name;
- 执行log函数,函数会被放入到调用栈中执 行;
- 调用bar()函数,被压入到调用栈中,但是执 行未结束;
- bar因为调用了sum,sum函数被压入到调 用栈中,获取到结果后出栈;
- bar获取到结果后出栈,获取到结果result;
- 将log函数压入到调用栈,log被执行,并且 出栈
浏览器中事件循环
如果执行JS中存在异步操作,例如setTimeout(),则会被放入调用栈中,执行会结束,不会阻塞后面代码运行
其实内部调用 web API,在合适的时机将函数加入到事件队列中
事件队列中的函数会被放入调用栈,然后被执行。
宏任务、微任务
事件循环中事实上有两个队列
- 宏任务队列(macrotask queue):ajax、setTimeout、setInterval、DOM监听、UI Rendering等
- 微任务队列(microtask queue):Promise的then回调、 Mutation Observer API、queueMicrotask()等
那么事件循环对于两个队列的优先级是怎么样的呢?
- main script中的代码优先执行(编写的顶层script代码);
- 在执行任何一个宏任务之前(不是队列,是一个宏任务),都会先查看微任务队列中是否有任务需要执行
- 也就是宏任务执行之前,必须保证微任务队列是空的;
- 如果不为空,那么久优先执行微任务队列中的任务(回调)
面试题
1
setTimeout(function () { console.log("set1"); new Promise(function (resolve) { resolve(); }).then(function () { new Promise(function (resolve) { resolve(); }).then(function () { console.log("then4"); }); console.log("then2"); }); }); new Promise(function (resolve) { console.log("pr1"); resolve(); }).then(function () { console.log("then1"); }); setTimeout(function () { console.log("set2"); }); console.log(2); queueMicrotask(() => { console.log("queueMicrotask1") }); new Promise(function (resolve) { resolve(); }).then(function () { console.log("then3"); }); // pr1 // 2 // then1 // queuemicrotask1 // then3 // set1 // then2 // then4 // set2
2
async function async1 () { console.log('async1 start') await async2(); console.log('async1 end') } async function async2 () { console.log('async2') } console.log('script start') setTimeout(function () { console.log('setTimeout') }, 0) async1(); new Promise (function (resolve) { console.log('promise1') resolve(); }).then (function () { console.log('promise2') }) console.log('script end') // script start // async1 start // async2 // promise1 // script end // aysnc1 end // promise2 // setToueout
注意:
Promise中的为同步代码块,then后为异步 微任务
Async 函数中:await前的可以看做Promise外部的diamante
await相当于在执行Promise中的为同步代码块
await后的相当于在执行then的回调 微任务

浙公网安备 33010602011771号