EventLoop
-
EventLoop本质是JS引擎的事件处理 主线程和调用栈的任务执行
-
JavaScript单线程
-
GUI线程 渲染布局
-
JS引擎线程 解析执行JS 与GUI线程互斥
-
定时触发器线程 (setTimeout setInterval
- 定时任务可能不会按时执行 (因所执行函数的延时等
- 嵌套5次之后最小间隔不能低于4ms
-
时间触发线程 将满足触发条件的时间放入任务队列
-
异步HTTP请求线程 XHR所在的线程
-
-
任务分为两种
-
宏任务
- script全部代码 setTimeout setInterval setImmediate IO UI Rendering
-
微任务
- Process.nextTick(Node) Promise object.observe(废弃) MutationObserver
-
-
console.log('script start') //async 本质上一个promise async function async1() { //await 会阻塞后面的代码 await async2() //await后面的代码 好比一个新then函数 console.log('async1 end') } async function async2() { console.log('async2 end') } async1() setTimeout(function() { console.log('setTimeout') }, 0) new Promise(resolve => { console.log('Promise') resolve() }) .then(function() { console.log('promise1') }) .then(function() { console.log('promise2') }) console.log('script end') /* script start async2 end Promise script end async1 end promise1 promise2 setTimeout */ async function async1() { console.log('async1 start'); await async2(); console.log('async1 end'); } async function async2() { await async3(); console.log('async2'); } async function async3() { console.log('async3'); } 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 async3 promise1 script end async2 promise2 async1 end undefined setTimeout */
-
Node EventLoop
Node.js的运行机制如下:
- V8引擎解析JavaScript脚本
- 解析后的代码,调用Node API
- libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎
- V8引擎再将结果返回给用户
timer
执行setTimeout setInterval回调
poll
执行顺序:
回到timer阶段执行回调
执行I/O回调
check
Process.nextTick的优先级大于其他的微任务
在Node.js中 微队列存在队列顺序 按先进先出的原则
区别
在同步代码上的处理保持一致
浏览器环境下,microtask的任务队列是每个macrotask执行完之后执行。而在Node.js中,microtask会在事件循环的各个阶段之间执行,也就是一个阶段执行完毕,就会去执行microtask完成队列的任务
在node - 11 版本上 执行顺序和浏览器保持一致
console.log('start')
setTimeout(() => {
console.log('timer1')
Promise.resolve().then(function() {
console.log('promise1')
})
}, 0)
setTimeout(() => {
console.log('timer2')
Promise.resolve().then(function() {
console.log('promise2')
})
}, 0)
Promise.resolve().then(function() {
console.log('promise3')
})
console.log('end')
/* node 中执行顺序 */
//start end promise3 timer1 timer2 promise1 promise2
/* 浏览器 中执行顺序 */
//start end promise3 timer1 promise1 timer2 promise2