热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

浏览器与NodeJS的EventLoop异同,以及部份机制。

浏览器与NodeJS的EventLoop异同,以及部份机制PS:有人对promise部份疑惑,Promise自身组织函数是同步的,.then是异步。—-20187622:35修正j

浏览器与NodeJS的EventLoop异同,以及部份机制

PS:有人对promise部份疑惑,Promise自身组织函数是同步的,.then是异步。—- 2018/7/6 22:35修正

Javascript 是一门单线程的脚本语言,虽然是单线程然则有很多异步的API来协助开发者处置惩罚线程的壅塞题目。比如:onClick 注册的回调函数、必不可少的ajax等等…然则 Javascript 运转环境是如何做到单线程却又不是一向壅塞线程守候种种异步操纵完成才继承实行操纵的呢?
答案就是: event loop

1.event loop 的范例是在HTML5中划定的。
2.event loop 是 Javascript 运转环境(手动加粗) 的机制。
3.浏览器完成的event loop 与 NodeJS 完成的event loop 是有异同的。

HTML5 中定义 event loop 范例链接
https://www.w3.org/TR/html5/w…

一 浏览器的event loop

1.简朴相识

event loop 即事宜轮回,它究竟是什么构造呢? 阮一峰先生的博客有一张图,虽然很直白、清晰明了然则少了一些东西不能周全的将 event loop 团体轮回机制展现出来。先来看图:
《浏览器与NodeJS的EventLoop异同,以及部份机制。》

图片非笔者原创,来自阮一峰博客,在此申明,侵删。

从图中我们能够获得信息是:

1.Javascript 引擎实行 Javascript 是单线程的,由于只要一个 stack 内里有种种正在实行、守候实行的事宜。

2.有一些 webAPI 将实行时发生的 callback 放入一个行列,即 “事宜行列”。

3.在event loop 轮回中不断的将“事宜行列”里守候实行的事宜,推入 Javascript 实行栈。

这就是事宜轮回简化的机制,为何说简化呢?由于在轮回中还做了很多没有说起的操纵、划定规矩。

我就不举栗子了,然则我要打个比如。
《浏览器与NodeJS的EventLoop异同,以及部份机制。》

《浏览器与NodeJS的EventLoop异同,以及部份机制。》

就说一个陈词滥调的题目 (文章编辑不轻易,直接一行了,换行党你却是来打我啊!)

setTimeout(e=>{ console.log(1) },0);
new Promise((res,rej)=>{ res() }).then(e=>{ console.log(2) });

一样都是 Javascript 中供应的异步API,一样都是直接实行( 开发者所愿望的,虽然会由于壅塞致使延时,防备杠精 ),然则不管这俩行代码谁上、谁下,输出都邑是 2 1。由于这里触及 event loop 中 macro taskmicro task 的实行递次、划定规矩。

2.团体流程
回到适才说那张流程图不够完美的题目上,如今来一张完整的、周全的 event loop 流程图。
《浏览器与NodeJS的EventLoop异同,以及部份机制。》

图片非笔者原创,来secrets of Javascript ninja,在此申明,侵删。

这是一个 event loop 完整的流程图,从图中我们看到了很多适才未说起的名词,重新至尾的梳理一遍 (从上至下):

1.读取 Macrotask queue 中使命。有俩种状况

  • 使命行列空,向下实行
  • 使命行列不为空,将最早进入的一个(手动+文章加粗)使命推入 Javascript 实行栈,向下实行

2.读取 Microtask queue 中使命。有俩种状况

  • 使命行列空,向下实行
  • 使命行列不为空,将最早进入的一个使命推入 Javascript 实行栈,而且再次反复此操纵(手动+文章加粗),直到 Microtask queue 为空。直白的说:将此使命行列依据先后递次将一切使命推入Javascript 实行栈,向下实行

3.依据
本次轮回耗时(手动+文章加粗)推断是不是
须要、是不是
能够更新UI 【 背面会提一下这个轮回时刻题目 】

  • 不须要,反复第一步
  • 须要,向下实行

4.更新UI,UI rendering,同时壅塞 Javascript 实行。而且继承反复第一步。

以上就是一悉数 event loop 流程,从流程中我们能够看到有俩个“使命行列”,这俩个行列实例化到 Javascript 中的API 就是

Macrotask queue --> setTimeout || setInterval || Javascript代码
Microtask queue --> Promise.then()

至此一个完整的 event loop 流程便完整说完了。

3.实例剖析
什么鬼?这么庞杂? 弄懂?不存在的
《浏览器与NodeJS的EventLoop异同,以及部份机制。》

如今回到适才提到的 “陈词滥调的题目” 从实例的角度来申明一下题目。我们假定这个 Javascript 文件叫做 “main.js”
“main.js”中的代码(+ 为自定义标记)

+1 console.log(1);
+2 setTimeout(e=>{ console.log(2); },0)
+3 setTimeout(e=>{ console.log(3); },0)
+4 new Promise((resolve,reject)=>{ console.log(4); resolve();})
.then(e=>{ console.log(5); })
+5 setTimeout(e=>{ console.log(6);
+6 new Promise((resolve,reject)=>{ console.log(7); resolve(); })
.then(e=>{ console.log(8);})
})

那末这个实行递次是如何呢?重新带尾梳理一遍(词穷,全文只假如流程统一是“重新至尾梳理一遍”)

macrotask: Javascript 代码,一切同步代码实行。输出:
1 4。注册 +4 到 microtask。 注册+2 +3 +5 到 macrotask。

microtask: 实行 +4 输出:
5

macrotask: 实行 +2。 输出
2

microtask:

macrotask: 实行 +3。 输出
3

microtask:

macrotask: 实行 +5。 输出
6 7。 注册 +6 到 microtask。

microtask: 输出
8

所以整体输出的递次为:1 4 5 2 3 6 7 8

假如这个输出与你所想雷同,那末基本就没有题目了。
那末假如不对或许有题目怎么办?
《浏览器与NodeJS的EventLoop异同,以及部份机制。》

PS: 前面提到 【本次轮回耗时】这个题目,这里我也不是异常清晰,望大牛指导。浏览器平常衬着页面60/S,以抵达每秒60帧(60 fps),所以也许16ms一次,既然有了时刻我们不经就会问?前面的使命处置惩罚耽误了则么办?由于Javascript线程与UI线程互斥,某些使命致使 Javascript引擎 坑了队友,自然而然没法在16ms的节点上抵达这一步,从secrets of Javascript ninja中相识到,平常会摒弃此次衬着,守候下一次轮回。( 若有题目请斧正! )

浏览器中的 event loop 到此完毕,下面说说 NodeJS 的 event loop

二 NodeJS的event loop

NodeJS 的 event loop 也是有 Macrotask queue 与 Microtask queue 的。只不过 NodeJS 的略有差别。那末主要说说差别在那里。

NodeJS中 Macrotask queue 与 Microtask queue 实例化到API为:
Macrotask queue --> script(主程序代码),setImmediate, I/O,setTimeout, setInterval
Microtask queue --> process.nextTick, Promise

1.Macrotask queue 差别之处

上面说到了浏览器 event loop 的 Macrotask queue 在每次轮回中只会读取一个使命,NodeJS 中 Macrotask queue 会一次性读取终了( 同阶段的实行终了,背面会说到Macrotask queue 分为 6个阶段 ),然后向下读取Microtask。

注重: 这一条与 NodeJS版本有很大关联,在看 深入浅出NodeJS 这一本书时( 看的版本很旧,不知是不是有修订版,若有请示知。 ),提到的 setImmediate 每次轮回只会实行一次,而且给出的示例在 v8.9.1 版本跑时已不相符书中所写。书中示例以下(+ 为自定义标记,原文中没有):


+1 process.nextTick(function () {
console.log('nextTick实行1');
});
+2 process.nextTick(function () {
console.log('nextTick实行2');
});
+3 setImmediate(function () {
console.log('setImmediateჽ实行1');
+4 process.nextTick(function () {
console.log('强势插进去');
});
});
+5 setImmediate(function () {
console.log('setImmediateჽ实行2');
});
+6 console.log('一般实行');
一般实行
nextTick实行1
nextTick实行2
setImmediate实行1
强势插进去
setImmediateჽ实行2

在 v8.9.1 中截图以下
《浏览器与NodeJS的EventLoop异同,以及部份机制。》

从图片中能够看到,至少在 v8.9.1 版本中 Macrotask queue 会直接悉数实行。依据通例重新至尾的梳理一遍

macrotask: Javascript 代码,一切同步代码实行。输出:
一般实行。注册 +3 +5 到 Macrotask。实行process.nextTick(),终究输出:
一般实行, nextTick实行1, nextTick实行2。

**microtask: 无

macrotask: 实行 +3 +5。 输出:
setImmediate实行1, setImmediateჽ实行2。 实行process.nextTick(),终究输出:
setImmediate实行1, setImmediateჽ实行2,强势插进去。

microtask:

所以终究输出为:一般实行, nextTick实行1, nextTick实行2,setImmediate实行1, setImmediateჽ实行2,强势插进去。

2.process.nextTick(),setImmediates,以及event loop的6个阶段

NodeJS 中 Macrotask queue会分为 6 个阶段,每一个阶段的作用以下(process.nextTick()在6个阶段完毕的时刻都邑实行):

timers:实行setTimeout() 和 setInterval()中到期的callback。
I/O callbacks:上一轮轮回中有少数的I/Ocallback会被延晚到这一轮的这一阶段实行
idle, prepare:仅内部运用
poll:最为主要的阶段,实行I/O callback,在恰当的条件下会壅塞在这个阶段
check:实行setImmediate的callback
close callbacks:实行close事宜的callback,比方socket.on("close",func)

注:此6个阶段非笔者原创来自
https://cnodejs.org/topic/5a9…,文章从底层C代码剖析NodeJS event loop。这里做只做简朴整合。侵删。

在相识了这六个阶段后,我们能够发明定时器系列在NodeJS event loop中 Macrotask queue 读取递次为:

1. setTimeout(fun,0) setInterval(fun,0)
2. setImmediate

空口无凭,在实例中相识。的代码送上( 代码较长,分为三段,轻易浏览,防止转动。 ):


+1 process.nextTick(function(){
console.log("1");
});
+2 process.nextTick(function(){
console.log("2");
+3 setImmediate(function(){
console.log("3");
});
+4 process.nextTick(function(){
console.log("4");
});
});
+5 setImmediate(function(){
console.log("5");
+6 process.nextTick(function(){
console.log("6");
});
+7 setImmediate(function(){
console.log("7");
});
});

+8 setTimeout(e=>{
console.log(8);
+9 new Promise((resolve,reject)=>{
console.log(8+"promise");
resolve();
}).then(e=>{
console.log(8+"promise+then");
})
},0)
+10 setTimeout(e=>{ console.log(9); },0)
+11 setImmediate(function(){
console.log("10");
+12 process.nextTick(function(){
console.log("11");
});
+13 process.nextTick(function(){
console.log("12");
});
+14 setImmediate(function(){
console.log("13");
});
});

console.log("14");
+15 new Promise((resolve,reject)=>{
console.log(15);
resolve();
}).then(e=>{
console.log(16);
})

这么庞杂的异步嵌套在一起是不是是很头疼呢?
我!不!看!了!

《浏览器与NodeJS的EventLoop异同,以及部份机制。》

末了一遍梳理,最多、最全的一次梳理。自古以来重新至尾的梳理一遍

macrotask: Javascript 代码,一切同步代码实行。输出:
14。实行process.nextTick(),终究输出:
14,15, 1, 2, 4。 注册 +3 +5 +8 +11 到 Macrotask。 注册 +15 到 Microtask。

microtask: 实行 +15 输出 16

macrotask: 实行 +8 +10 输出
8, 8promise, 9。 注册 +9 到 Microtask。

microtask: 实行 +9 输出
8promise+then

macrotask: 实行 +5 +11 +3 输出 5, 10, 3。 注册 +7 +14 到
macrotask。实行process.nextTick(),终究输出:
5 10 3 6 11 12。

microtask:

macrotask: 实行 +7 +14。 输出:
7,13

microtask:

由此最中悉数的输出为:14,15,1,2,4,8,8promise,9,8promise+then,5,10,3,6,11,12,7,13

三 完毕

到此完毕了。浏览器的、NodeJS 的 event loop 已悉数份析完成,过程当中援用:阮一峰博客,知乎,CSDN部份文章内容,侵删。

最近在相识部份底层学问,收成颇丰。个中包含 for of…. 等等种种奇奇怪怪的题目,有时刻再写吧。

末了,本人菜鸟,若有不对、不实、误导等毛病、题目,迎接批评区斧正。


推荐阅读
  • 前段时间做一个项目,需求是对每个视频添加预览图,这个问题最终选择方案是:用canvas.toDataYRL();来做转换获取视频的一个截图,添加到页面中,达到自动添加预览图的目的。 ... [详细]
  • 工作经验谈之-让百度地图API调用数据库内容 及详解
    这段时间,所在项目中要用到的一个模块,就是让数据库中的内容在百度地图上展现出来,如经纬度。主要实现以下几点功能:1.读取数据库中的经纬度值在百度上标注出来。2.点击标注弹出对应信息。3 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • 服务器上的操作系统有哪些,如何选择适合的操作系统?
    本文介绍了服务器上常见的操作系统,包括系统盘镜像、数据盘镜像和整机镜像的数量。同时,还介绍了共享镜像的限制和使用方法。此外,还提供了关于华为云服务的帮助中心,其中包括产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题和视频帮助等技术文档。对于裸金属服务器的远程登录,本文介绍了使用密钥对登录的方法,并提供了部分操作系统配置示例。最后,还提到了SUSE云耀云服务器的特点和快速搭建方法。 ... [详细]
  • 本文介绍了一种处理AJAX操作授权过期的全局方式,以解决Asp.net MVC中Session过期异常的问题。同时还介绍了基于WebImage的图片上传工具类。详细内容请参考链接:https://www.cnblogs.com/starluck/p/8284949.html ... [详细]
  • 一、什么是闭包?有什么作用什么是闭包闭包是定义在一个函数内部的函数,它可以访问父级函数的内部变量。当一个闭包被创建时,会关联一个作用域—— ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • [翻译]PyCairo指南裁剪和masking
    裁剪和masking在PyCairo指南的这个部分,我么将讨论裁剪和masking操作。裁剪裁剪就是将图形的绘制限定在一定的区域内。这样做有一些效率的因素࿰ ... [详细]
  • 必须先赞下国人npm库作品:node-images(https:github.comzhangyuanweinode-images),封装了跨平台的C++逻辑,形成nodejsAP ... [详细]
  • javascript二叉树基本功能实现
    都是常用的功能。删除是最复杂的。。test ... [详细]
  • Arduino + ESP32C3 + TFT(1.8‘ ST7735S)基础平台(实验四)直接显示网络图片
    ------------------------------------------------------------------------------------------ ... [详细]
  • 1、概述首先和大家一起回顾一下Java消息服务,在我之前的博客《Java消息队列-JMS概述》中,我为大家分析了:然后在另一篇博客《Java消息队列-ActiveMq实战》中 ... [详细]
author-avatar
mobiledu2502878025
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有