vlambda博客
学习文章列表

今日艰难笔记-浏览器和Node下的eventloop

先给出一个知识点,在JS中有些代码是异步执行的,所谓异步,就是不会阻塞代码的运行,而会另外开启一个空间去执行这段异步代码,(!并不是另开一个线程,同一时间执行多件事)其余同步的代码就仍正常执行,若异步代码中有其它的代码,则会在之后的某个时刻将异步代码中其它代码执行。例如上述代码中的 setTimeout 函数就是异步的,而其内部还有一段同步代码 console.log('2')

这里提到的某个时刻,也正是我们本文后续要讲到的重点,这里就先不做过多讲解

那么异步执行的额外空间是哪里来的?那当然是JS所处的运行环境提供的了,而JS最主要的两个运行环境就是:浏览器  Node,我们接下来也会基于这两个运行环境,对JS的运行机制进行讲解

浏览器中的各种 Web API 为异步的代码提供了一个单独的运行空间,当异步的代码运行完毕以后,会将代码中的回调送入到 Task Queue(任务队列)中去,等到调用栈空时,再将队列中的回调函数压入调用栈中执行,等到栈空以及任务队列也为空时,调用栈仍然会不断检测任务队列中是否有代码需要执行,这一过程就是完整的Event Loop 了

  • 下面列举了浏览器中常用的宏任务和微任务

名称 举例(常用)
宏任务 setTimeout 、setInterval 、UI rendering
微任务 promise 、requestAnimationFrame

并且规定,当宏任务和微任务都处于 Task Queue 中时,微任务的优先级大于宏任务,即先将微任务执行完,再执行宏任务

  • Node.js的Event Loop 是基于libuv实现的

   通过 Node.js 的官方文档可以得知,其事件循环的顺序分为以下六个阶段,每个     阶段都会处理专门的任务:

  • timers: 计时器阶段,用于处理setTimeout以及setInterval的回调函数
  • pending callbacks: 用于执行某些系统操作的回调,例如TCP错误
  • idle, prepare: Node内部使用,不用做过多的了解
  • poll: 轮询阶段,执行队列中的 I/O 队列,并检查定时器是否到时
  • check: 执行setImmediate的回调
  • close callbacks: 处理关闭的回调,例如 socket.destroy()

以上六个阶段,我们需要重点关注的只有四个,分别是 timers 、poll 、check 、close callbacks

这四个阶段都有各自的宏队列,只有当本阶段的宏队列中的任务处理完以后,才会进入下一个阶段。在执行的过程中会不断检测微队列中是否存在待执行任务,若存在,则执行微队列中的任务,等到微队列为空了,再执行宏队列中的任务(这一点与浏览器非常类似,但在Node 11.x版本之前,并不是这样的运行机制,而是运行完当前阶段队列中的所有宏任务以后才会去检测微队列。对于11.x 之后的版本,虽然在官网我还没找到相关文字说明是这样的,但通过无数次的运行,暂且可以说是这样的,若各位找到相关的说明,可以留下评论)

同理,Node.js也有宏任务和微任务之分,我们来看一下常用的都有哪些

名称 举例(常用)
宏任务 setTimeout 、setInterval 、setImmediate
微任务 Promise 、process.nextTick

可以看到,在Node.js对比浏览器多了两个任务,分别是宏任务 setImmediate 和 微任务 process.nextTick

setImmediate 会在 check 阶段被处理

process.nextTick 是Node.js中一个特殊的微任务,因此会为它单独提供一个队列,称为 next tick queue,并且其优先级大于其它的微任务,即若同时存在 process.nextTick 和promise,则会先执行前者

总结一下,Node.js在事件循环中涉及到了4个宏队列和2个微队列,如图所示





     图为node环境下eventloop



附一直迷惑的浏览器内核是啥? 点击阅读原文

浏览器组成可分两部分:Shell+内核。浏览器内核又可以分成两部分:渲染引擎(layout engineer或者Rendering Engine)和JS引擎。

渲染引擎功能作用

       渲染引擎,负责对网页语法的解释(如HTML、JavaScript)并渲染网页。所以,通常所谓的浏览器内核也就是浏览器所采用的渲染引擎,渲染引擎决定了浏览器如何显示网页的内容以及页面的格式信息。不同的浏览器内核对网页编写语法 的解释也有不同,因此同一网页在不同的内核的浏览器里的渲染(显示)效果也可能不同,这也是网页编写者需要在不同内核的浏览器中测试网页显示效果的原因。


当前主流四大引擎内核:

 

Trident,Gecko,Presto,Webkit

JS引擎功能作用

      最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。JavaScript最初由网景公司的Brendan Eich设计,是一种动态、弱类型、基于原型的语言,内置支持类。以它为基础,制定了ECMAScript标 准。JavaScript在浏览器的实现中还必须含有DOM和BOM。Web浏览器一般使用公共 API来创建主机对象来负责将DOM对象反射进JavaScript。JS引擎负责对JavaScript进行解释、编译和执行,以使网页达到一些动态的效果。
主要的网页浏览器JavaScript引擎:

1) Mozilla

  • Rhino,由Mozilla基金会管理, 开放源代码,完全以Java编写。

  • SpiderMonkey,第一款JavaScript引擎,由Brendan Eich在Netscape Communications时编写,用于Mozilla Firefox1.0~3.0版本。

  • TraceMonkey,基于实时编译的引擎,其中部份代码取自Tamarin引擎,用于 Mozilla Firefox 3.5~3.6版本。

  • JägerMonkey,(JägerMonkey,也有人拼写成JagerMonkey)德文Jäger原意为猎人,结合追踪 和组合码技术大幅提高效能,部分技术借凿了V8、JavaScriptCore、WebKit,用于Mozilla Firefox 4.0以上版本。

2)Google

  • V8,开放源代码,由Google丹麦开发,是Google Chrome的一部分。

3)微软

  • Chakra,中文译名为查克拉,用于Internet Explorer 9

  •  JScript 是由微软公司开发的活动脚本语言,是微软对ECMAScript规范的实现.IE 3.0-IE8.0使用的JS引擎

4)其它


    • KJS,KDE的 ECMAScript/JavaScript引擎,最初由Harri Porten开发,用于KDE项目的 Konqueror网页浏览器中。

    • Narcissus,开放源代码, 由Brendan Eich编写(他也参与编写了第一个SpiderMonkey)。

    • Tamarin,由Adobe Labs编写,Flash Player 9所使用的引擎。

    • Nitro(原名SquirrelFish),为Safari 4编 写。

    • Carakan,由Opera软件公司编写,自Opera10.50版 本开始使用。