5调用外部浏览器打开代码_浏览器事件循环

浏览器运行过程中会同时面对多种任务,用户交互事件(鼠标、键盘)、网络请求、页面渲染等。而这些任务不能是无序的,必须有个先来后到,浏览器内部需要一套预定的逻辑来有序处理这些任务,因此浏览器事件循环诞生了,再次强调,是浏览器事件循环,不是javascript事件循环,js只是浏览器事件循环的参与者。

二、事件循环是什么

浏览器把任务区分成了 宏任务 和 微任务 或者叫 外部任务 和 内部任务 ,内部任务可以理解为js内部处理的任务,外部任务可以认为是浏览器处理的任务。

外部队列/宏任务队列(Task Queue)

也可以叫宏任务队列,浏览器中的外部事件源包含以下几种:

  • dom操作(页面渲染)
  • 用户交互(鼠标、键盘)
  • 网络请求(Ajax等)
  • History API操作(history.back、history.go...)
  • 定时器(setTimeout)

这些外部事件源可能很多,为了方便浏览器厂商优化,HTML标准中明确指出一个事件循环有一个或多个外部队列,而每一个外部事件源都有一个对应的外部队列。不同的时间源之间可以有不同的优先级(例如在网络时间和用户交互之间,浏览器可以优先处理鼠标行为,从而让用户感觉更加流畅)。

内部队列/微任务队列(Microtask Queue)

也可以叫微任务队列,指的就是javascript语言内部的事件队列,在HTML标准中,并没有明确规定这个队列的事件源,通常认为有以下几种:

  • Promise的成功(.then)与失败(.catch)
  • MutationObserver
  • Object.observe(已废弃)

以上三种除了第一个,其他两个可以认为没有,实际上我们js中能够使用的就只有promise。

事件循环模型

先来一张事件循环处理模型的截图:

e02c83a2bc91ef8463089dc939c4ef4b.png

可以看出,每一个事件循环,从外部任务队列中拿出一个来执行,执行完一个外部任务后立即执行内部任务队列中所有内部任务(清空),然后浏览器执行一次渲染,然后再次循环。

一段经典代码

了解了两种队列和事件循环的执行模型,下面来一段经典代码:

// 以下代码会得到什么样的输出结果?console.log('1');setTimeout(function() {   console.log('2');   Promise.resolve().then(function() {console.log('3');   });}, 0);Promise.resolve().then(function() {   console.log('4');}).then(function() {   console.log('5');});console.log('6');

答案是:164523

执行顺序如下:

  • 由于执行当前js代码这个任务是一个宏任务,因此首先输出的是"1",
  • 继续执行遇到setTimeou,由于setTimeout是一个外部事件源,它内部的代码会被push到TaskQueue中等待下一次事件循环再执行,
  • 当执行到promise的 then 或 catchd的时候会将他们按顺序追加到本轮事件循环的末尾,
  • 再继续往下执行输出6,宏任务完成后清空微任务队列中的任务,继而输出4、5
  • 如果有的话,执行渲染任务后,本次事件循环结束
  • 开始执行下一个宏任务,也就是第一个setTimeout中的代码块,输出2,然后将promise.then添加到本轮循环末尾
  • 清空微任务,输出3

三、浏览器与Node.js的事件循环差异

区别对比

对于两者的区别,来张瞟来的截图:

af115827ad1d5e091a44f2cb6b25d932.png

这个例子的代码如下:

setTimeout(()=>{   console.log('1');   Promise.resolve().then(function() {console.log('2'); });});setTimeout(()=>{   console.log('3');   Promise.resolve().then(function() {console.log('4');   });});

这段代码在浏览器和nodejs中的输出结果分别是什么呢?

通过前面对浏览事件循环的了解,你应该很容易得出在浏览器中的输出结果是: 1234

那在nodejs中的输出结果是什么呢?结果是在nodejs的 v11.x 之前输出1324。这之间的原因是浏览器有非常多的用户交互事件,为了用户体验更加流畅,必须均匀的处理宏任务和微任务,而在nodejs中由于并没有用户交互事件,为了保证异步事件能够被均等的执行,因此设计的初衷就是先清空宏任务队列再清空微任务队列。

不过你应该注意到,我上面只说了在 nodejs的 v11.x 之前输出1324,但是nodejs这个特性在社区经历了一波开发者的吐槽之后,node官方在 v11 这个版本紧急修复了这个问题。所以在 v11.x 以上版本执行以上代码会得到在浏览器中一样的结果。

setImmediate

先来张瞟来的截图:

1c7331058507500c8d7ec88ee4b77d05.png

我们再来一个例子:

setTimeout(()=>{console.log('1');Promise.resolve().then(() => console.log('2'));});setTimeout(()=>{  console.log('3');  Promise.resolve().then(() => console.log('4'));});setImmediate(() => {console.log('5');   Promise.resolve().then(() => console.log('6'));});setImmediate(() => {console.log('7');   Promise.resolve().then(() => console.log('8'));});

以上代码在nodejsV13.x中的执行结果是12345678,接下来我们把顺序调换一下,在第二个位置插入setImmediate

setTimeout(()=>{console.log('1');Promise.resolve().then(() => console.log('2'));});setImmediate(() => {console.log('3');   Promise.resolve().then(() => console.log('4'));});setTimeout(()=>{  console.log('5');  Promise.resolve().then(() => console.log('6'));});setImmediate(() => {console.log('7');   Promise.resolve().then(() => console.log('8'));});

执行结果有一定的概率是12347856,也有一定的概率是 12563478

为啥不同的顺序会得到不同的结果呢?这是由于setTImeout的精度问题导致的,到了这个级别的时间精度,代码执行的时间可能都会导致结果的不同。下面这张截图是nodejs官方文档对于事件循环顺序的展示:

cc94f27aec63c0c7da860c9894a63265.png

其中timers阶段是用于执行setTimeout事件的,check阶段是用于执行setImmediate事件的。Nodejs官方这个所谓事件循环过程,其实只是完整的事件循环中Node.js的多个外部队列相互之间的优先级。setTimeout是由event loop检测系统时间是否到点然后向时间队列插入一个事件,然后调用事件的回调方法。而setImmediate是监控UI线程的调用栈,一旦调用栈为空则将回调压栈。

讲了这么多,其实对于上面setTimeout和setImmediate的对比结果还是有点模糊

推测:对于setImmediate的延时有时比setTimeout的要长,由于setImmediate要先监控调用栈,若调用栈为空才压栈,那么在压栈之前event loop已经将setTimeout事件的回调函数压栈了。

好了,以上是这次分享的所有内容,对于后面setTimeout和setImmedate的对比没有的出一个明确的结果,有兴趣的可以一起讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356176.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM上的高并发HTTP客户端

HTTP可能是最流行的应用程序级别协议,并且有许多库在网络I / O之上实现它,这是常规I / O的一种特殊(面向流)情况。 由于所有I / O都有很多共同点1 ,所以让我们开始对其进行一些讨论。 我将集中讨论具有大量并发HTTP请…

win10系统卷影复制服务器,如何使用Windows卷影拷贝服务恢复文件和文件夹

本文介绍了如何使用Windows卷影拷贝服务恢复文件和文件夹,分享给大家,具体如下:什么是卷影拷贝?从Windows XP SP2和Windows Server 2013开始,微软就向Windows操作系统中引入了一项名叫卷影拷贝的服务(Volume Shadow Co…

Nginx下配置Http Basic Auth

nginx basic auth指令 第一条语句: 语法: auth_basic string | off;默认值: auth_basic off;配置段: http, server, location, limit_except 默认表示不开启认证,后面如果跟上字符,这些字符会在弹窗中显示。 第二条语句&#xff…

服务器多核性能排行,服务器内存多核性能

服务器内存多核性能 内容精选换一换本文介绍了弹性云服务器ECS的功能发布和对应的文档动态,新特性将在各个区域(Region)陆续发布,欢迎体验。关于弹性云服务器(ECS)更多历史版本变更内容,请单击“查看PDF”详细了解。超高I/O型弹性云服务器使用…

从去除毛刺的策略看开运算opening_circle和闭运算closing_circle的异同

例一:毛刺在往外凸的面上 策略1:分割出黑色部分,然后通过开运算去掉毛刺,再通过原黑色部分区域减去开运算之后的区域,得到毛刺部分的区域。 1 read_image (Tu, C:/Users/xiahui/Desktop/tu.jpg) 2 binary_threshold (…

买服务器带操作系统,买服务器带操作系统

买服务器带操作系统 内容精选换一换只有运行中的弹性云服务器才允许用户登录。Linux操作系统用户名“root”。忘记密码,请先通过“重置密码”功能设置登录密码。重置密码:选中待重置密码的云耀云服务器,并选择“操作”列下的“ 重置密码”。重…

自定义sql_【PL/SQL 自定义函数】 常用场景

看完这章后你会学习到以下内容:1.练习场景2.面试场景3.工作应用场景总览思维导图:面试部分:1.创建函数,从emp表中查询指定员工编号的职工的工资CREATE OR REPLACE FUNCTION CHECK_SAL(F_EMPNO IN EMP.EMPNO%TYPE) RETURN NUMBER ISV_SAL VARC…

进阶– Java EE 7前端5强

系列继续。 在初步概述和Arjan关于最重要的后端功能的文章之后 ,我现在非常高兴让Ed Burns( edburns )使用他最喜欢的Java EE 7前端功能完成本系列。 感谢Markus Eisele让我有机会在他非常受欢迎的博客上发表帖子。 我和Markus的关系可以追溯…

一杯水怎么测试_一杯水就能鉴别翡翠真假的高招

大家好,小生有礼!鄙人是秋玉蝉珠宝的杨杨,很高兴能在茫茫互联网中相识就是有缘。先简单介绍一下秋玉蝉珠宝,我们是年轻的品牌,我们的理念一直秉承坚持做真翡翠,好翡翠,把握翡翠的精髓&#xff0…

php连接mysql_PHP连接MySQL数据库的三种方式

本篇文章给大家介绍一下PHP连接MySQL数据库的三种方式(mysql、mysqli、pdo),结合实例形式分析了PHP基于mysql、mysqli、pdo三种方式连接MySQL数据库的相关操作技巧与注意事项。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助…

idea内置junit5_JUnit的内置Hamcrest Core Matcher支持

idea内置junit5在通过JUnit和Hamcrest改善对assertEquals的文章中,我简要讨论了Hamcrest “ 核心 ”匹配器与JUnit的现代版本“结合”在一起的情况。 在那篇文章中,我特别关注了JUnit的assertThat(T,Matcher)静态方法与…

jenkins 发送邮件模板

jenkins 发送邮件模板 <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>${ENV, var"JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title> </head><body leftmargin"8" marginwidth"…

Oracle Spring Clean JavaFX应该吗?

我们确实在Codename One上依赖JavaFX&#xff0c;我们的模拟器需要它。 我们的桌面版本使用它&#xff0c;而我们的设计器工具基于Swing。 我们希望它成功&#xff0c;这对我们的业务至关重要&#xff01; 即使您是Java EE开发人员并且不关心桌面编程&#xff0c;我们也不是一个…

laravel mysql 锁表_Laravel中MySQL的乐观锁与悲观锁

MySQL/InnoDB的加锁&#xff0c;是一个老生常谈的话题。在数据库高并发请求下&#xff0c;如何兼顾数据完整性与用户体验的敏捷性是一代又一代程序员一直在思考的问题。乐观锁乐观锁之所以叫乐观&#xff0c;是因为这个模式不会对数据加锁。而是对数据操作保持一种乐观的心态&a…

mysql 超长记录_谁记录了mysql error log中的超长信息(记pt-stalk一个bug的定位过程)...

【问题】最近查看MySQL的error log文件时&#xff0c;发现有很多服务器的文件中有大量的如下日志&#xff0c;内容很长(大小在200K左右)&#xff0c;从记录的内容看&#xff0c;并没有明显的异常信息。有一台测试服务器也有类似的问题&#xff0c;为什么会记录这些信息&#xf…

glassfish发布应用_Arquillian 1.0.0.Final正式发布! 准备使用GlassFish和WebLogic! 所有虫子死亡!...

glassfish发布应用红帽公司和JBoss社区今天宣布的1.0.0.Final发布的Arquillian &#xff0c;其屡获殊荣的建在Java虚拟机&#xff08;JVM&#xff09;运行测试平台。 Arquillian大大减少了编写和执行Java中间件集成和功能测试所需的工作。 它甚至使测试工程师能够解决以前认为无…

使用ADF列表视图的主从数据

最近&#xff0c;从UI角度来看&#xff0c;ADF Faces 表组件不再被认为很酷。 对于显示数据集合&#xff0c; 列表视图今天应该很酷。 这并不意味着我们根本不应该使用af&#xff1a;table 。 在某些情况下&#xff08;经常是:)&#xff09;&#xff0c;表比列表视图更适合。 但…

java 调用私有方法_公开调用私有Java方法?

java 调用私有方法我们是Java开发人员&#xff0c;在Java中已知4种访问修饰符&#xff1a;私有&#xff0c;受保护&#xff0c;公共和包。 好吧&#xff0c;除了私有以外&#xff0c;最后三个可以通过继承&#xff0c;相同的包或实例从类外部调用。 现在&#xff0c;常见的问题…

港航环境变化引起的错误解决方法

1.serlvet API缺少&#xff0c;pom.xml中引入坐标&#xff1b; 2.web.xml中出现错误&#xff0c;将所有的filter调到filtermapping上面去&#xff1b; 3.依赖导入完成后项目依然有红叉&#xff0c;右击项目Propreties->myeclipse->Project Facets->java换成1.6就可以了…

flutter 国际化_从0开始设计Flutter独立APP | 第二篇: 完整的国际化语言支持

鉴于Flutter高性能渲染和跨平台的优势&#xff0c;闪点清单在移动端APP上&#xff0c;使用了完整的Flutter框架来开发。既然是完整APP&#xff0c;架构搭建完全不受历史Native APP的影响&#xff0c;没有历史包袱的沉淀&#xff0c;设计也能更灵活和健壮。国际化语言的支持&…