We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
改自 dwqs/blog#61
有如下题目:
new Promise(resolve => { resolve(1) Promise.resolve().then(() => console.log(2)) console.log(4) }).then(t => { console.log(t) }) console.log(3) // 输出 4 3 2 1
JavaScript 是 单线程 的,即同一时间只能做一件事。为了协调事件、用户交互、脚本、UI 渲染与网络处理等行为以及防止主线程被阻塞,事件循环(Event Loop)应运而生
Event Loop 包含两类:
二者运行是独立的,即每一个 JavaScript 运行的线程环境都有一个独立的 Event Loop,每一个 Web Worker 也有一个独立的 Event Loop
事件循环是通过任务队列机制协调的:
在事件循环中,每进行一次循环操作称之为 Tick,每一次 Tick 的任务处理模型是复杂的,关键步骤如下:
阅读规范可知,异步任务分为 Task(MacroTask 宏任务) 与 MicroTask(微任务) 两类,不同的 API 注册的异步任务会依次进入自身对应的队列中,然后等待 Event Loop 将它们依次压入执行栈中执行
MacroTask 包括:
MicroTask
注意:
setTimeout、Promise 等 API 便是任务源,而进入任务队列的是它们指定的具体任务,来自不同任务源的任务会进入到不同的任务队列:
console.log("Script Start") setTimeout(() => { console.log("timeout1") }, 10) new Promise(resolve => { console.log("promise1") resolve() setTimeout(() => console.log("timeout2"), 10) }).then(() => { console.log("then1") }) console.log("Script End")
接着遇到了 console.log() 语句,直接输出 Script Start。输出之后,Script 任务继续往下执行,遇到了 setTimeout,它作为一个 MacroTask,会将其任务分发到对应队列中:
console.log()
Script Start
setTimeout
Script 任务继续执行,遇到了 Promise 实例,Promise 构造函数中第一个参数是在 new 的时候执行的,执行时其中的参数进入执行栈执行;而后续的 .then 则被分发到 MicroTask 的 Promise 队列中去。因此会输出 Promise1,接着执行 resolve 并将 then1 分发到对应队列
Promise
.then
构造函数继续执行,遇到了 setTimeout,然后将其对应的任务分发到对应队列:
Sciprt 任务继续执行,最后输出 Sciprt End,至此全局任务执行完毕。当执行完一个 MacroTask 后,会检查是否存在 MicroTasks,若存在则执行 MicroTasks 直至清空 MicroTasks
Sciprt End
因此,在 Script 执行完毕后,开始查找清空 MicroTask Queue。此时,MicroTasks 中只有 Promise 队列的一个任务 then1,因此直接执行,输出 then1。当所有的 MicroTasks 执行完毕后,表示第一轮循环结束
此后开始第二轮循环,第二轮循环依然从 MacroTask 开始。此时,有两个任务:
取出 timeout1 执行,输出 timeout1。此时 MicroTask Queue 已经没有可执行的任务了,直接开始第三轮循环:
第三轮循环依旧从 MacroTask Queue 开始,此时 MacroTask Queue 只有一个 timeout2,取出并直接输出。此时,MacroTask Queue 与 MicroTask Queue 都没有任务了,因此将不会在输出其它东西。综上,输出结果如下:
Script Start promise1 Script End then1 timeout1 timeout2
本文最上方题目:
这段代码流程如下:
为什么 t2 先执行呢?
The text was updated successfully, but these errors were encountered:
No branches or pull requests
改自 dwqs/blog#61
资料
有如下题目:
事件循环
JavaScript 是 单线程 的,即同一时间只能做一件事。为了协调事件、用户交互、脚本、UI 渲染与网络处理等行为以及防止主线程被阻塞,事件循环(Event Loop)应运而生
Event Loop 包含两类:
二者运行是独立的,即每一个 JavaScript 运行的线程环境都有一个独立的 Event Loop,每一个 Web Worker 也有一个独立的 Event Loop
任务队列
事件循环是通过任务队列机制协调的:
在事件循环中,每进行一次循环操作称之为 Tick,每一次 Tick 的任务处理模型是复杂的,关键步骤如下:
阅读规范可知,异步任务分为 Task(MacroTask 宏任务) 与 MicroTask(微任务) 两类,不同的 API 注册的异步任务会依次进入自身对应的队列中,然后等待 Event Loop 将它们依次压入执行栈中执行
MacroTask 包括:
MicroTask
注意:
setTimeout、Promise 等 API 便是任务源,而进入任务队列的是它们指定的具体任务,来自不同任务源的任务会进入到不同的任务队列:
示例
接着遇到了
console.log()
语句,直接输出Script Start
。输出之后,Script 任务继续往下执行,遇到了setTimeout
,它作为一个 MacroTask,会将其任务分发到对应队列中:Script 任务继续执行,遇到了
Promise
实例,Promise 构造函数中第一个参数是在 new 的时候执行的,执行时其中的参数进入执行栈执行;而后续的.then
则被分发到 MicroTask 的 Promise 队列中去。因此会输出 Promise1,接着执行 resolve 并将 then1 分发到对应队列构造函数继续执行,遇到了 setTimeout,然后将其对应的任务分发到对应队列:
Sciprt 任务继续执行,最后输出
Sciprt End
,至此全局任务执行完毕。当执行完一个 MacroTask 后,会检查是否存在 MicroTasks,若存在则执行 MicroTasks 直至清空 MicroTasks因此,在 Script 执行完毕后,开始查找清空 MicroTask Queue。此时,MicroTasks 中只有 Promise 队列的一个任务 then1,因此直接执行,输出 then1。当所有的 MicroTasks 执行完毕后,表示第一轮循环结束
此后开始第二轮循环,第二轮循环依然从 MacroTask 开始。此时,有两个任务:
取出 timeout1 执行,输出 timeout1。此时 MicroTask Queue 已经没有可执行的任务了,直接开始第三轮循环:
第三轮循环依旧从 MacroTask Queue 开始,此时 MacroTask Queue 只有一个 timeout2,取出并直接输出。此时,MacroTask Queue 与 MicroTask Queue 都没有任务了,因此将不会在输出其它东西。综上,输出结果如下:
最初的题目
本文最上方题目:
这段代码流程如下:
为什么 t2 先执行呢?
The text was updated successfully, but these errors were encountered: