Open nmsn opened 1 year ago
浏览器是多线程的
js 的代码只能在一个线程上运行,也就是说同时只能执行一个 js 任务,原因是设计之初是浏览器用来供用户交互和操作 dom 的,避免复杂性,设计成这样的
既然JS是单线程的,那么诸如onclick回调,setTimeout,Ajax这些异步都是怎么实现的呢?是因为浏览器或node(宿主环境)是多线程的,即浏览器搞了几个其他线程去辅助JS线程的运行
负责渲染浏览器页面 html 元素,当界面需要重绘 repaint 或者某些操作引发回流 reflow 时,该线程就会执行
当 js 引擎运行脚本期间,gui 渲染线程都是处于挂起状态的
js 内核,负责处理 js 脚本主程序 一直等待 任务队列 中任务的到来,然后解析 js 脚本,运行代码 浏览器中的一个 tab (一个页面,也就是一个进程)中无论什么时候就只有一个 js 线程在运行 js 程序
gui 渲染线程和 js 引擎线程是互斥的,如果 js 执行的时间过长,就会造成页面的渲染不连贯,导致页面渲染加载阻塞
定时器 setInterval 与 setTimeout 所在的线程
浏览器定时器并不是 js 引擎技术的,因为 js 引擎单线程,如果处于阻塞线程状态就会影响计时的准确,因此通过单独线程来计时更为合理
定时器到时间后就会把回调函数放到任务队列中,等待 js 引擎处理
用来控制事件
当 js 引擎执行代码如鼠标点击 click,onload 等事件,会将对应任务添加到事件触发线程中
由于 js 单线程,这个待处理的任务队列中的事件都得排队等待 js 引擎处理
在 XMLHttpRequest 连接后是通过浏览器新开一个线程请求,将监测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件放到 js 引擎任务队列中等待处理
浏览器执行代码的过程中,js 引擎会讲代码进行分类,分别分到这两个队列中 宏任务 macrotask 和 微任务 microtask
微任务是宏任务的组成部分,微任务与宏任务是包含关系,并非前后并列,宏任务包含微任务,如果要谈微任务,需要指出它属于哪个宏任务才有意义
requestAnimationFrame 它既不能算宏任务,也并非是微任务.它的执行时机是在当前宏任务范围内,执行完同步代码和微任务队列后再执行.它仍然属于宏任务范围内,但是是在微任务队列执行完毕后才执行