# 5-事件循环机制 ## 宏任务, 微任务 ```js // 打印顺序 setTimeout(()=>( console.log(1) ),0) Promise.resolve(1).then(()=>{ console.log(2) }) console.log(3) ``` > js 是单线程的, 基于事件循环机制 (even loop) 来处理异步任务, 不断检查调用栈和任务队列 > 当调用栈中的代码执行完毕后, 队列中的代码才会按照顺序依次进入到栈中执行 > - 调用栈: 放要执行的代码 > - 栈: 是一种数据结构, 后进先出 (类似叠盘子) > - 全局作用域的代码, 是放在栈里的 > - 任务队列: 等待执行的代码 > - 队列: 是一种数据结构, 先进先出 (类似排队) > - 任务队列有两种: > - 宏任务队列: 大部分代码都去宏任务队列排队 > - 微任务队列: Promise 的回调函数 (then, catch, finally) ===执行顺序: 调用栈 \==> 微任务队列 \==> 宏任务队列=== * 调用栈包括: ```js 全局代码(例如变量声明、函数定义、同步函数调用等) ``` ```js console.log("Start"); function foo() { console.log("foo"); } foo(); console.log("End"); /** 1. 全局执行上下文被推入调用栈。 2. `console.log("Start")` 执行。 3. `foo()` 被推入调用栈。 4. `console.log("foo")` 执行,`foo()` 从调用栈弹出。 5. `console.log("End")` 执行。 6. 全局执行上下文从调用栈弹出。 */ ``` * 微任务包含: ```js Promise.then Object.observe MutationObserver // 突变观察者 process.nextTick(Node.js 环境) ``` Promise 在执行,then 就相当于给 Promise 设置了回调函数, 当 Promise 的状态从 pending 变为 fulfilled 时,then 的回调函数会被放入到微任务队列中 * 宏任务包含: ```js script(整个标签或整个外部文件) setTimeout setInterval I/O UI交互事件 postMessage MessageChannel setImmediate(Node.js 环境) ``` 定时器: 间隔一段时间后, 将函数放到宏任务队列 ### queueMicrotask 微任务队列 ```js // queueMicrotask 把函数添加到微任务队列 queueMicrotask(()=>{ console.log(5) }) ``` ```js Promise.resolve().then(()=>{ Promise.resolve().then(()=>{ console.log('a') }) }) queueMicrotask(()=>{ console.log('b') }) // b a ``` ```js console.log(1) setTimeout(() => console.log(2)) Promise.resolve().then(() => console.log(3)) Promise.resolve().then(() => setTimeout(() => console.log(4))) Promise.resolve(). then(() => console.log(5)) setTimeout(() => console.log(6)) console.log(7) ```