摘要:而当响应成功了以后,浏览器的事件表则会将回调函数添加至事件队列中等待执行。事件循环器会不停的检查事件队列,如果不为空,则取出队首压入执行栈执行。类型的任务目前包括了以及的回调函数。
事件循环(event loop) :
首先说事件队列(task queue)
事件队列是一个存储着待执行任务的队列,其中的任务严格按照时间先后顺序执行,排在队头的任务将会率先执行,而排在队尾的任务会最后执行。
事件队列每次仅执行一个任务,在该任务执行完毕之后,再执行下一个任务。
执行栈则是一个类似于函数调用栈的运行容器,当执行栈为空时,JS 引擎便检查事件队列,如果不为空的话,事件队列便将第一个任务压入执行栈中运行。
当我们设置一个延迟函数的时候,当前脚本并不会阻塞,它只是会在浏览器的事件表中进行记录,程序会继续向下执行。 当延迟的时间结束之后,事件表会将回调函数添加至事件队列中,事件队列拿到了任务过后便将任务压入执行栈(stack)当中,执行栈执行任务
事件循环机制:
检查事件队列是否为空,如果为空,则继续检查;如不为空,则执行 2;
取出事件队列的首部,压入执行栈;
执行任务
检查执行栈,如果执行栈为空,则跳回第 1 步;如不为空,则继续检查;
结合 Web APIs 事件循环:
ajax 请求挂起,然后继续执行后面的代码,至于请求何时响应,对我们的程序不会有影响,甚至它可能永远也不响应,也不会使浏览器阻塞。
而当响应成功了以后,浏览器的事件表则会将回调函数添加至事件队列中等待执行。
事件监听器的回调函数也是一个任务,当我们注册了一个事件监听器时,浏览器事件表会进行登记,当我们触发事件时,事件表便将回调函数添加至事件队列当中。
事件循环器会不停的检查事件队列,如果不为空,则取出队首压入执行栈执行。当一个任务执行完毕之后,事件循环器又会继续不停的检查事件队列,
不过在这间,任务结束后浏览器会对页面进行渲染。这就保证了用户在浏览页面的时候不会出现页面阻塞的情况,这也使 JS 动画成为可能,同步就没动画的渐变效果了。
总结:
事件队列严格按照时间先后顺序将任务压入执行栈执行;
当执行栈为空时,浏览器会一直不停的检查事件队列,如果不为空,则取出第一个任务;
在每一个任务结束之后,浏览器会对页面进行渲染;
- 接下来说一下不同的任务(task)之间的执行顺序问题
microtask
每一个 事件循环(event loop)都有着众多不同的任务来源(task source),这些来源能够保证其中的任务能够有序的执行。不过,在每一轮事件循环结束之后,浏览器可以自行选择将哪一个来源当中的任务加入到执行队列当中
任务Task是严格按照时间顺序 压栈和执行 的,当一个 task 执行结束后,在下一个 task 执行开始前,浏览器可以对页面进行重新渲染
Microtask 通常来说就是需要在当前 task 执行结束后立即执行的任务,
例如需要对一系列的任务做出回应,或者是需要异步的执行任务而又不需要分配一个新的 task,这样便可以减小一点性能的开销。microtask
任务队列是一个与 task 任务队列相互独立的队列, microtask 任务将会在每一个 task 任务执行结束之后执行。每一个
task 中产生的 microtask 都将会添加到 microtask 队列中, microtask 中产生的 microtask
将会添加至当前队列的尾部,并且 microtask 会按序的处理完队列中的所有任务。 microtask 类型的任务目前包括了
MutationObserver 以及 Promise 的回调函数。 microtask 执行在当前 task 结束之后,下一个 task 开始之前。
microtask 执行在当前 task 结束之后,下一个 task 开始之前。
另外补充一下上文说到的 Mutation Observer
使用链接见文章: https://segmentfault.com/a/11...
Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。 它等待所有脚本任务完成后,才会运行(即异步触发方式)。 它把 DOM 变动记录封装成一个数组进行处理,而不是一条条个别处理 DOM 变动。 它既可以观察 DOM 的所有类型变动,也可以指定只观察某一类变动。 observe方法用来启动监听,它接受两个参数。 第一个参数:所要观察的 DOM 节点 第二个参数:一个配置对象,指定所要观察的特定变动
总结:
microtask 和 task 一样严格按照时间先后顺序执行。
microtask 类型的任务包括 Promise callback和 Mutation callback。
当 JS 执行栈为空时,便生成一个 microtask 检查点。
最后 概括一些分类
macrotask: script (整体代码),setTimeout, setInterval, setImmediate, I/O, UI rendering. microtask: process.nextTick, Promise(原生),Object.observe,MutationObserver 在microtask中 process.nextTick 优先级高于 Promise。
对于任务名称的事件队列关系
task queue == macrotask queue != microtask queue
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/96972.html
摘要:异步任务必须指定回调函数,当异步任务从任务队列回到执行栈,回调函数就会执行。事件循环主线程从任务队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为。事件循环事件循环是指主线程重复从消息队列中取消息执行的过程。 参考链接:这一次,彻底弄懂 JavaScript 执行机制https://zhuanlan.zhihu.com/p/...从浏览器多进程到JS单线程,JS运行机制...
摘要:如果对语法分析和预编译,还有疑问引擎执行的过程的理解语法分析和预编译阶段。参与执行过程的线程分别是引擎线程也称为内核,负责解析执行脚本程序的主线程例如引擎。以上便是引擎执行宏任务的整个过程。 一、概述 js引擎执行过程主要分为三个阶段,分别是语法分析,预编译和执行阶段,上篇文章我们介绍了语法分析和预编译阶段,那么我们先做个简单概括,如下: 1、语法分析: 分别对加载完成的代码块进行语法...
摘要:如果对语法分析和预编译,还有疑问引擎执行的过程的理解语法分析和预编译阶段。参与执行过程的线程分别是引擎线程也称为内核,负责解析执行脚本程序的主线程例如引擎。以上便是引擎执行宏任务的整个过程。一、概述 js引擎执行过程主要分为三个阶段,分别是语法分析,预编译和执行阶段,上篇文章我们介绍了语法分析和预编译阶段,那么我们先做个简单概括,如下: 1、语法分析: 分别对加载完成的代码块进行语法检验,语...
摘要:规范中定义了浏览器何时进行渲染更新,了解它有助于性能优化。结合一些资料,对上边规范给出一些理解有误请指正每个线程都有自己的。列为,列为,列为。我们都知道是单线程,渲染计算和脚本运行共用同一线程网络请求会有其他线程,导致脚本运行会阻塞渲染。 本文转自blog 转载请注明出处 异步的思考 event loops隐藏得比较深,很多人对它很陌生。但提起异步,相信每个人都知道。异步背后的靠山就是...
阅读 536·2021-10-19 11:45
阅读 1345·2021-09-30 09:48
阅读 1463·2021-08-16 10:56
阅读 726·2021-07-26 23:38
阅读 3206·2019-08-30 13:15
阅读 2589·2019-08-30 12:45
阅读 1823·2019-08-29 12:14
阅读 2059·2019-08-26 18:42