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,一经查实,立即删除!

相关文章

服务器生成文件怎么配置路径,npm run build生成的文件如何部署到服务器上

其实楼上两个人的回答都是对的,只不过侧重点不一样,一楼是大的方面说,配置好服务器就可以了,该怎么运行就怎么运行,只不过没有部署过项目的人可能就不知道怎么回事了;二楼说的应该是配置windos服务器的环境…

JVM上的高并发HTTP客户端

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

linux下解析域名

linux下解析域名<?xml version"1.0" encoding"UTF-8"?> vi /etc/resolv.confnameserver 208.67.222.222 #opendnsnameserver 208.67.220.220sudo vim /etc/network/interfacesnull转载于:https://www.cnblogs.com/iceiceiceice/p/e64ca5a0b5941c7…

tomcat加白名单_超详细的tomcat管理页面各类型配置总结

概述大部分时候&#xff0c;我们的tomcat服务器都不是部署在本机&#xff0c;那么怎么样不通过ftp/sftp方式来将war包部署到tomcat容器呢&#xff1f;tomcat有提供web页面管理应用的功能。tomcat页面管理进入tomcat默认页面时有“server status”、“manager app”、“Host man…

服务器系统报错kernel-power,第十二讲、Linux服务器操作系统1.ppt

第十二讲、Linux服务器操作系统1.ppt4.1引导与关闭系统 4.1.1 GRUB引导器 GRUB简介 1)grub?是一个多重启动管理器。grub是GRand?Unified?Bootloader的缩写&#xff0c;它可以在?多个操作系统共存时选择引导哪个系统&#xff0c;它不仅可以对各种发行版本的Linux进行引导&am…

Java 关键字 transient

Java 关键字 transient转载于:https://www.cnblogs.com/fysola/p/6394626.html

小程序picker标题_微信小程序-自定义picker选择器

avatar为什么要自定义picker原生小程序picker不支持自定义样式&#xff0c;无联动。该自定组件支持自定义数据支持自定义样式支持传入和返回对象或者基本类型支持联动(改变父列&#xff0c;子列根据关联自动变化)使用直接将picker文件夹拖入工程在某page的json文件中配置{"…

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

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

openshift s2i_对Openshift上的Play Framework 2应用进行故障排除

openshift s2iOpenshift故障排除 使用“ 自己动手”应用程序类型&#xff0c;您实际上可以有很大的自由度来支持几乎可以在Linux机器上构建和运行的任何框架或服务器。 但是您必须做功课&#xff0c;并做一些研究。 因此&#xff0c;在本文中&#xff0c;我将向您展示一些我在使…

Nginx下配置Http Basic Auth

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

aopaspect区别_面试官:什么是AOP?Spring AOP和AspectJ的区别是什么?

面向切面的编程(AOP) 是一种编程范式&#xff0c;旨在通过允许横切关注点的分离&#xff0c;提高模块化。AOP提供切面来将跨越对象关注点模块化。AOP要实现的是在我们写的代码的基础上进行一定的包装&#xff0c;如在方法执行前、或执行后、或是在执行中出现异常后这些地方进行…

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

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

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

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

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

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

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

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

让一个非窗口组件(non-windowed component)可以接受来自Windows的消息

为什么要这样做&#xff1f;有时候我们需要一个非窗口组件(比如一个非继承自TWinContrl的组件)可以接受Windows消息。要接受消息就需要一个窗口句柄&#xff0c;但是非窗口组件却没有句柄。这篇文章将讲述怎么让一个没有句柄的组件如何通过一个隐藏的窗口接受消息这是怎么做到的…

进阶– Java EE 7前端5强

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

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

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

214

python 进程&#xff1a;process 线程&#xff1a;thread转载于:https://www.cnblogs.com/jtlin/p/6397533.html

SpringBoot:与MyBatis合作

MyBatis是一个SQL映射框架&#xff0c;支持自定义SQL&#xff0c;存储过程和高级映射。 SpringBoot不为MyBatis集成提供官方支持&#xff0c;但MyBatis社区为MyBatis构建了SpringBoot入门程序。 您可以在http://blog.mybatis.org/2015/11/mybatis-spring-boot-released.html上…