JS事件循环机制
2020-09-22 20:36:14 0 举报
AI智能生成
js事件循环机制
作者其他创作
大纲/内容
JS事件循环机制
浏览器中的EventLoop
js单线程机制
what
所有任务都在一个线程上完成
所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着
why
假定JavaScript 同时有两个线程,一个线程在某个 DOM 节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?
为了避免复杂性,从一诞生,JavaScript 就是单线程,这已经成了这门语言的核心特征
how
js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue(任务队列)那里检查是否有等待被调用的函数
任务分类
同步任务
同步任务进入主线程
在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务
异步任务
js异步机制
就是遇到宏任务,先执行宏任务,将宏任务放入宏任务队列
然后在执行微任务,将微任务放入微任务队列
当你往外拿的时候先从微任务队列拿这个回调函数并执行,然后再从宏任务的队列上拿宏任务的回调函数并执行
异步任务进入Event Table并注册回调函数
不进入主线程、而进入\"任务队列\"(task queue)的任务,只有\"任务队列\"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行
宏任务(macrotask)
分类
setTimeOut
setInterval
setImmediate
I/O
callback
优先级
主代码块 > setImmediate > MessageChannel > setTimeOut/setInterval
特点
宏任务队列每次只会取出一条任务到执行栈中执行
requestAnimationFrame 在页面重绘前,当前微任务执行后再执行宏任务
先进先出
微任务(microtask)
process.nextTick
Promise
MutationObserver
async(实质上也是promise)
process.nextTick > Promise > MutationOberser
微任务队列操作,总是会一次性清空队列
浏览器会在一个宏任务结束后,检查是否有微任务开始执行
下一次宏任务,必须要等到当前微任务执行完毕,才可以执行
执行分区
内存
执行栈
所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)
主线程之外,还存在一个\"任务队列\"(task queue)。只要异步任务有了运行结果,就在\"任务队列\"之中放置一个事件
一旦\"执行栈\"中的所有同步任务执行完毕,系统就会读取\"任务队列\",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行
只要主线程空了,就会去读取\"任务队列\",这就是JavaScript的运行机制。这个过程会不断重复
WebApi
ajax
events
mouse click
key press
scroll
network events
timing
。。。
异步回调队列
宏任务队列
宏任务总会在下一个EventLoop中执行
若在执行宏任务的过程中,加入了新的微任务,会把新的微任务添加到微任务的队列中
微任务队列
若在执行微任务的过程中,加入了新的微任务,会把新的微任务添加在当前任务队列的队尾
微任务会在本轮EventLoop执行完后,马上把执行栈中的任务都执行完毕
执行流程
Javascript内核加载代码到执行栈
执行栈依次执行主线程的同步任务,过程中若遇调用了异步Api则会添加回调事件到回调队列中。且把微任务事件添加到微任务队列中,宏任务事件添加到宏任务队列中去。直到当前执行栈中代码执行完毕
开始执行当前所有微任务队列中的微任务回调事件
取出宏任务队列中的第一条(先进先出原则哦)宏任务,放到执行栈中执行
执行当前执行栈中的宏任务,若此过程总又再遇到微任务或者宏任务,继续把微任务和宏任务进行各自队伍的入队操作,然后本轮的宏任务执行完后,又把本轮产生的微任务一次性出队都执行了
以上操作往复循环...就是我们平时说的eventLoop了
Node 环境中的EventLoop
渲染引擎
渲染引擎是多线程的,包含ui线程和js线程。ui线程和js线程会互斥,因为js线程的运行结果会影响ui线程,ui更新会被保存在队列,直到js线程空闲,则被取出来更新
运行机制
V8引擎解析JavaScript脚本
解析后的代码,调用Node API
libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎
V8引擎再将结果返回给用户
node任务队列
队列
timers(计时器队列)执行,setTimeout以及setInterval的回调
I/O callbacks(输入输出队列), 处理网络,流,TCP的错误 ,callback
poll(轮询队列),执行poll中的i/o队列检查定时器是否到时
check(检查队列),存放setImmediate回调
close callbacks(关闭队列),如socket.on('close')
注意
这里的每一个阶段都对应着一个事件队列
当Event Loop进入到某个阶段的时候,就会将该阶段队列里的回调拿出来执行,直到队列为空
开始循环后,每次拿出当前阶段的全部任务执行,清空NextTick队列,清空微任务队列,再执行下一阶段,全部6个阶段完毕后,进入下一轮的循环
同步、异步,阻塞、非阻塞
同步
即为调用者等待被调用者这个过程,如果被调用者一直不反回结果,调用者就会一直等待,这就是同步,同步有返回值
异步
即为调用者不等待被调用者是否返回,被调用者执行完了就会通过状态、通知或者回调函数给调用者,异步没有返回值
阻塞
指当前线程在结果返回之前会被挂起,不会继续执行下去
非阻塞
即当前线程不管你返回什么,都会继续往下执行
0 条评论
回复 删除
下一页