异步与事件环

文章目录

异步

EventLoop 事件环

进程是计算机分配任务和调度任务的最小单位

浏览器是一个多进程模型,有一个主进程(用户界面),每个页卡都是独立的渲染进程(浏览器内核)。后端代码都是采用多进程。

常见的渲染线程及功能:

1. GUI 渲染:页面渲染、绘图、绘制 3d 动画
2. js 引擎: 执行 js 代码,js 执行时,渲染线程会挂起,即渲染时不能执行 js
3. 事件触发进程 EventLoop
4. webApi 也会创建线程,如事件(click 等)、定时器、ajax 请求
5. webworker

JS 是单线程的,指的是主线程是单线程的,实际上上面这些都是线程。

宏任务、微任务

宏任务: <script> 脚本、UI 渲染、setTimeout、setInterval、postMessage、MessageChangel(I / O 操作)、setImmediate(只存在于 ie)

微任务:promise、MutationObserer、object.observe(已被废弃,有 bug)、process.nextTick(只存在于 node 环境)、queueMircotask

每循环一次会执行一个宏任务,并清空对应的微任务队列,每次事件循环完毕后会判断页面是否需要重新渲染,大约 16.6 ms 会渲染一次

image-20210616221006486

requestFrameAnimation 的渲染时机是微任务被清空的时候

  1. 先执行 script 脚本,将宏任务和微任务进行分类,如果调用的是浏览器 api,浏览器会开一个线程,等事件到了,自动地放入到宏任务队列中,微任务是直接放到微任务队列中的
  2. js 执行完毕后,会清空所有的微任务,如果微任务再产生微任务,会放到当前微任务队列的尾部
  3. 如果页面需要渲染,则执行渲染流程(即在微任务之后,在一轮脚本执行完之后才会触发!requestFrameAnimation 、idleCallback 都是在这时候触发的)

事件触发线程会不停扫描宏任务队列,如果宏任务队列中有对应的回调,会取出来执行一个,继续执行上述的过程

微任务队列每次执行宏任务,都会创建一个微任务队列,而宏任务队列只有一个。

任务的优先级

宏任务macrotask:主代码块 > setImmediate > MessageChannel > setTimeout / setInterval(大部分浏览器会把DOM事件回调优先处理 因为要提升用户体验 给用户反馈,其次是network IO操作的回调,再然后是UIrender,之后的顺序就难以捉摸了,其实不同浏览器的表现也不太一样,这里不做过多讨论。)

微任务microtask:process.nextTick > Promise = MutationObserver

分享到:

评论完整模式加载中...如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理