My Little World

关于事件循环event-loop

js单线程

同一时间只干一件事,干完一件事再干下一件事,
如果前一个任务耗时很长,后一个任务也得一直等着

为什么这样设计?
js 要指挥浏览器干活,如果有两个线程同时执行任务,一个删除DOM,一个修改该DOM,浏览器会不知道以哪个线程为准

任务队列

同步任务,在主线程上排队执行的任务,前一个执行完才能执行后一个任务
异步任务,一开始不进入主线程,而进入‘任务队列’被挂起,只有‘任务队列’通知主线程某个异步任务可以执行了,该任务才会进入主线程
或者主线程上没有要执行的任务了,就会去任务队列拿任务 ,在确认该到达规定时间后,就给到主线程进行执行其对应的回调函数

event Loop

主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)
setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,即尽可能早得执行
另外如果主线程的栈中当前代码耗时很长,要等很久,按照先主线程,再任务队列的执行顺序,
就没办法保证setTimeout的回调函数fn能够在指定的时间执行

node.js event loop

nodejs 运行机制:
(1)V8引擎解析JavaScript脚本。
(2)解析后的代码,调用Node API。
(3)libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎。
(4)V8引擎再将结果返回给用户。

与任务队列相关方法
process.nextTick:在主线程任务全部结束后,读取任务队列的任务之前执行它所指定的函数,
如果指定函数里还套嵌process.nextTick方法,或者有多个process.nextTick方法,都要在本轮读取任务队列前执行完
setImmediate:它指定的任务总是在下一次的eventloop时执行,
如果setImmediate与setTimeout(fn,0)各自添加了一个回调函数,那么在下一loop时,他们回调函数的顺序是不确定
如果setImmediate套嵌setImmediate方法,则套嵌的回调函数会被注册到下一轮事件循环中再执行

即多个process.nextTick语句总是在当前”执行栈”一次执行完,多个setImmediate可能则需要多次loop才能执行完。

相关链接

补充

task/macrotask:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
setTimeout() 设置的异步延迟事件;
DOM 操作相关如布局和绘制事件;
网络 I/O 如 AJAX 请求事件;
用户操作事件,如鼠标点击、键盘敲击。
micotask:process.nextTick, Promises(这里指浏览器实现的原生 Promise), Object.observe, MutationObserver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
process.nextTick(() => {
console.log('nextTick')
})
Promise.resolve()
.then(() => {
console.log('then')
})
setImmediate(() => {
console.log('setImmediate')
})
console.log('end')

//结果
end
nextTick
then
setImmediate

micro-task在ES2015规范中称为Job,
promise.then的执行其实是向PromiseJobs添加Job

在eventloop中,一个task执行完会检查micotask队列,如果有,则先执行micotask,然后再去异步队列领取任务
相关
相关
相关