js Event Loop 事件循环执行机制
Published:
·
LastMod: May 04, 2022
·
1411 words
Javascript engine list 🔗
- V8 — open source, developed by Google, written in C++
- Rhino — managed by the Mozilla Foundation, open source, developed entirely in Java
- SpiderMonkey — the first JavaScript engine, which back in the days powered Netscape Navigator, and today powers Firefox
- JavaScriptCore — open source, marketed as Nitro and developed by Apple for Safari
- KJS — KDE’s engine originally developed by Harri Porten for the KDE project’s Konqueror web browser
- Chakra (JScript9) — Internet Explorer
- Chakra (JavaScript) — Microsoft Edge
- Nashorn, open source as part of OpenJDK, written by Oracle Java Languages and Tool Group
- JerryScript — is a lightweight engine for the Internet of Things.
V8把JavaScript代码编译成机器码,而不是使用解释器.
它通过像许多现代 JavaScript 引擎(例如 SpiderMonkey 或 Rhino (Mozilla))一样实现 JIT(即时)编译器,在执行时将 JavaScript 代码编译成机器代码
v8不生成任何字节码或者其他中间代码
异步(asynchronous [eɪˈsɪŋkrənəs])执行运行机制 🔗
- 所有同步任务都在主线程上执行,形成一个执行栈
- 主线程之外还存在一个任务队列,异步任务有了结果,就会在任务队列中放置一个事件
- 同步任务执行完毕后,系统就会读取任务队列中的任务
宏任务 🔗
- I/O
- setTimeout
- setInterval
- setImmediate(node.js)
- requestAnimationFrame
微任务 🔗
Promise.then
process.nextTick(node.js)
MutationObserver
Node.js中的Event Loop 🔗
Node.js
采用v8作为js的解析引擎,I/O处理方面采用libuv
运行机制:
- v8解析javascript脚本文件
- 调用Node API
- libuv负责Node API的执行。把任务分配给不同的线程,形成EventLoop, 把结果以异步的方式返回给v8引擎
- v8把结果返回给用户
nodejs的event loop分为6个阶段 🔗
- timers:执行setTimeout() 和 setInterval()中到期的callback。
- I/O callbacks:上一轮循环中有少数的 I/O callback 会被延迟到这一轮的这一阶段执行
- idle, prepare:队列的移动,仅内部使用
- poll:最为重要的阶段,执行I/O callback,在适当的条件下会阻塞在这个阶段
- check:执行setImmediate的callback
- close callbacks:执行close事件的callback,例如socket.on(“close”,func)
注意点 🔗
- 每个阶段完成后,都会执行清空微任务队列
- timers阶段执行创建的setImmediate事件,会在本轮循环的check阶段执行完毕,而timers阶段创建的setTimeout事件,会进入下轮循环执行
- Node中同个MicroTask队列下, process.nextTick比Promise更加优先
事件循环执行代码解析 🔗
|
|
- 开头是一个自执行函数, 执行到
count1
- a函数调用
count2
- a里面调用b,b是一个异步函数,这里b会执行
count4
- 回到a函数,
count3
推送微任务队列 - 回到一开始的自执行函数,往下执行
count1-1
- 自执行函数同步任务执行完毕,主任务同步任务执行
- 执行到new Promise
count6
打印, then方法推到微任务队列- 往下执行,一个setTimeout推入宏任务队列
count9
打印- 微任务队列执行,先入先出原则
- 执行
count3
- 执行
count7
- 宏任务队列执行
- 执行
count8
,宏任务重产生微任务 - 清空微任务,打印
count8-1