浏览器事件循环(Event Loop)
彻底搞懂有多少种任务同步任务微任务宏任务在 JavaScript 引擎V8的字典里根本没有“异步任务”这个词只有“同步任务”和“回调函数”。同步任务属于宏任务但宏任务不一定是同步任务。所有的同步代码其实都是第一个默认的“宏任务”。真正的微任务只有这几个Promise.then/catch/finally、MutationObserver、queueMicrotask。常见的宏任务setTimeout、setInterval、I/O操作、UI 渲染、全局 script 代码。普通的异步请求如 fetch / ajax虽然它们是异步的但它们属于 I/O 操作执行完后的回调会被放入宏任务队列中等待执行。有多少种任务队列微任务队列宏任务队列类比厨师为js引擎单线程即一整个js代码片段厨师要做什么菜是同步任务客人又点了可乐但是厨师在炒饭所以厨师直接给了服务员webapis去做可乐“异步任务”-区分同步任务的说法这里的可乐我们给他设定为promise.then在做完菜之后微任务有插队机制所以厨师需要先给可乐结束所有微任务之后再给炒饭之后厨师就回去做下一道菜从宏任务里面取出同步任务继续循环。【执行一个宏任务】 ➡️ 【清空所有微任务】 ➡️ 【执行下一个宏任务】 ➡️ 【清空所有微任务】...无限循环console.log(1. 同步代码); setTimeout(() { console.log(2. setTimeout 宏任务); // 注意在宏任务内部又产生了微任务 Promise.resolve().then(() { console.log(7. 第一个 setTimeout 里的微任务); }); }, 0); setTimeout(() { console.log(8. 第二个 setTimeout 宏任务); }, 0); Promise.resolve().then(() { console.log(3. Promise 微任务); }); async function asyncFn() { console.log(4. async 函数内的同步代码); await Promise.resolve(); console.log(5. async 函数内 await 后的代码); } asyncFn(); console.log(6. 同步代码结束);✅ 正确的打印顺序是1 - 4 - 6 - 3 - 5 - 2 - 7 - 8阅读整个js片段js引擎开始执行同步代码直接输出将微任务放入微任务队列宏任务放入宏任务队列第一轮console输出1第一个settimeout的回调进入宏任务不管第二个settimeout的回调进入宏任务不管promise的回调进入微任务不管调用函数asyncFn() - 进入内部 - console输出4 - await 关键字后面的代码相当于被放进了 Promise.then 中所以直接进入微任务不管console输出6结果1 4 6第二轮检查微任务队列promise的回调console输出3await 关键字后面的代码console输出5结果1 4 6 3 5第三轮检查宏任务队列第一个settimeoutconsole输出2后面跟了一个promise的回调进入微任务不管这个时候当前宏任务结束在下一个宏任务开始之前检查微任务队列结果1 4 6 3 5 2第四轮检查微任务队列promise的回调console输出7微任务结束结果 1 4 6 3 5 2 7第五轮检查宏任务队列第二个settimeoutconsole输出8结果1 4 6 3 5 2 7 8