欢迎您访问无忧自考网!

百度工程师带你体验引擎中的nodejs

更新时间:2023-01-07 16:50:59作者:51data

作者|糖果糖果

百度工程师带你体验引擎中的nodejs

指导阅读

简介如果你是一个前端程序员,不了解PHP、Python或者Ruby之类的动态编程语言,然后想创建自己的服务,那么Node.js是一个非常好的选择。Node.js是运行在服务器端的Javascript。如果你熟悉JavaScript,你会很容易学会Node.js。当然,如果你是一个后端程序员,想要部署一些高性能的服务,那么学习Node.js也是一个非常好的选择。全文6723字,预计阅读时间时间17分钟。

极客用语

01

Node.js是什么?我们先来看看Node.js的官方定义:Node.js是一个基于V8 JavaScript引擎的JavaScript运行时环境。

但是这句话可能有点笼统:1。什么是JavaScript运行时环境?2.JavaScript为什么需要特殊的运行环境?3.JavaScript引擎又是什么?4.V8是什么?带着这些问题,我们先来了解一下nodejs的历史。在Node.js出现之前,最常见的JavaScript运行时环境是浏览器,也称为JavaScript的托管环境。它为JavaScript提供了DOM API,使JavaScript能够操作浏览器环境(JS环境)。2009年初,Node.js出现了。它是基于Chrome V8引擎开发的JavaScript运行时环境,所以Node.js也是JavaScript的宿主环境。而它的底层是我们熟悉的Chrome浏览器的JavaScript引擎,所以本质上和Chrome浏览器中运行的JavaScript没什么区别。但是Node.js的运行环境还是和浏览器不一样。通俗地说,Node.js执行的是基于V8引擎的JavaScript代码,而不仅仅是V8引擎。我们知道V8可以嵌入到任何C应用中,无论是Chrome还是Node.js其实就是嵌入了V8引擎来执行JavaScript代码。但在Chrome浏览器中,还需要解析和渲染HTML、CSS等相关渲染引擎。此外,还需要提供支持浏览器操作的API、浏览器自带的事件循环等。另外,我们还需要在Node.js中做一些额外的操作,比如文件系统读/写,网络IO,加密,压缩解压文件等。那么我们来看看浏览器是如何解析渲染的。

极客用语

02

浏览器如何渲染页面?

简单来说,用浏览器渲染网页可以分为以下几个步骤:

HTML解析:在这个过程之前,浏览器会进行DNS解析、TCP握手等网络协议相关的操作,以建议连接用户需要访问的域名服务器。域名服务器会返回一个HTML文本给用户,以便后期渲染(这个很重要,请注意)。渲染树构建:浏览器客户端收到服务器返回的HTML文本后,会对HTML文本进行解析,其中会用DOM生成DOM树来确定页面的布局结构,用CSS生成CSS树来确定页面元素的样式。如果在这个过程中遇到脚本或者静态资源,会预先加载请求静态资源,最后生成渲染树。布局:浏览器得到渲染树后,会做布局操作,确定页面上每个对象的大小和位置,然后进行渲染。渲染:我们电脑的视图都是通过GPU的图像帧来显示的。渲染的过程其实就是把上面得到的渲染树转换成GPU的图像帧进行显示。首先浏览器会根据布局树的位置进行栅格化(用过组件库的同学应该比较熟悉,就是把页面按照行列划分成相应的图层,比如12个网格,根据相应的网格列确定位置),最后得到一个复合框架,包括文字、颜色、边框等。其次,将复合帧升级为GPU的图像帧,然后显示在页面上,让我们在电脑上看到自己的页面。相信看到这里,你对浏览器如何渲染页面有了一个大概的了解。其实页面渲染就是浏览器将HTML文本转换成相应页面框架的过程。页面的内容和呈现过程与第一步获取的HTML文本密切相关。

极客用语

03

循环和异步IO:首先我们要知道什么是事件循环。然后我们需要知道流程和在线的概念。

还有进程和线程:都是操作系统的概念。进程:计算机已经运行的程序,线程:操作系统可以调度来启动应用程序的最小单元。默认情况下,会启动一个(或多个)进程。每个进程都会启动一个线程来执行程序中的代码,这个线程就叫做主线程。举例:比如工厂相当于操作系统,工厂里的车间相当于流程,车间里的工人相当于线程,所以流程相当于线程的容器。

那么浏览器是一个过程吗?里面只有一根线吗?目前浏览器一般都是多进程的。通常,当一个标签被打开时,一个新的进程将被启动。这是为了防止所有页面因为一个页面卡住而无法响应,需要强制退出整个浏览器。每个进程包含多个线程,包括执行js代码的线程。js代码在一个单独的线程中执行。单线程一样时间。它只能做一件事。如果这非常耗时,则意味着当前线程将被阻塞。浏览器时间循环维护两个队列:宏任务队列和微任务队列。

Macrotask queue):ajax、setTimeout、setInterval、DOM监控、UI渲染等。微任务队列:然后回调承诺。那么这两个队列的事件循环的优先级是什么呢?

main中的代码优先(编写的顶层脚本代码);在执行任何一个宏任务(不是队列,是宏任务)之前,我们都会先检查一下微任务队列中是否有任务要执行,也就是说,在执行宏任务之前,我们必须保证微任务队列是空的;如果不为空,微任务队列(回调)中的任务会先执行这么久。New promise()是同步,promise.then、promise.catch、resolve和reject是微任务。

极客用语

04

使用事件驱动程序Node.js来使用事件驱动模型。当web服务器收到一个请求时,它会关闭并处理它,然后为下一个web请求提供服务。当请求完成时,它被放回处理队列,当它到达队列的开始时,结果被返回给用户。这种模型非常高效且可伸缩,因为web服务器总是接受请求而不等待任何读写操作。(这也称为非阻塞IO或事件驱动IO)在事件驱动模型中,会生成一个主循环来侦听事件,并在检测到事件时触发一个回调函数。

整个事件驱动的过程就是这样实现的,非常简洁。类似于观察者模式,一个事件相当于一个主体,在这个事件上注册的所有处理函数都相当于观察者。Node.js有许多内置事件。我们可以通过引入events模块并实例化EventEmitter类来绑定和监视事件,如下例所示:

//引入事件模块var events=require(' events ');//创建eventEmitter对象var event emitter=new events . event emitter();下列程序绑定事件处理程序:

//绑定事件及其处理程序eventemitter.on ('eventname 'eventhandler);我们可以通过程序触发事件:

//触发事件event emitter . emit(' event name ');使用以下代码创建一个实例main.js文件:

//引入事件模块var events=require(' events ');//创建eventEmitter对象var event emitter=new events . event emitter();//创建事件处理程序var connect handler=function connected(){ console . log('连接成功~ ~ ~ ');//触发data_received事件event emitter . emit(' data _ received ');}//绑定连接事件处理程序eventemitter.on ('connection 'connect handler);//绑定data_received事件eventemitter.on ('data _ received 'function(){ console . log(' data is received。'));});//触发连接事件event emitter . emit(' connection ');Console.log('程序完成了。');接下来让我们执行上面的代码:

$ node main.js连接成功~ ~ ~接收数据。程序结束了。

极客用语

05

Node.js架构及其与浏览器的区别

上图是Node.js的基本架构,我们可以看到,(Node.js运行在操作系统上),它的底层由V8 JavaScript引擎,以及一些C/C编写的库组成,包括libUV库,c-ares,llhttp/http-parser,open-ssl,zlib等等。

其中libUV负责处理事件周期,c-ares、llhttp/http-parser、open-ssl、zlib等库提供DNS解析、http协议、HTTPS和文件压缩功能。

这些模块的上层是中间层,包括Node.js绑定、Node.js标准库和C/C插件。Node.js绑定层的作用是将C/C编写的库接口暴露给js环境,Node.js标准库是Node.js本身的核心模块。至于C/C插件,它允许用户自己的C/C模块通过桥接提供给Node.js。

中间层是Node.js的API层,我们使用Node.js开发应用,主要是使用Node.js的API层,所以Node.js的应用最终运行在Node.js的API层上。

总结一下:Node.js系统的架构图主要由四部分组成:应用、V8 javascript引擎、Node.js绑定、libuv。

应用:nodejs应用是我们写的js代码。V8: JavaScript引擎,分析js代码后调用节点api。Node.jsbindings:节点API,最终由libuv驱动。Libuv:异步I/O,实现异步无阻塞的核心模块。libuv库提供的两个最重要的东西是事件循环和线程池,它们共同构建了一个异步非阻塞I/O模型。按纬度划分,线程可以分为Node.js线程和其他C线程。应用程序启动一个线程,并在Node.js线程中完成它。Node.js的I/O操作是非阻塞的,大量的计算能力被分配给其他C线程。在C线程完成计算后,结果被回调到Node.js线程,然后该线程将内容返回给应用程序。浏览器中的事件循环是按照HTML5规范实现的,不同的浏览器可能有不同的实现,而libuv是在node中实现的。因为Node.js不是浏览器,所以没有浏览器提供的DOM API。

如窗口对象、位置对象、文档对象、HTMLElement对象、Cookie对象等。但是Node.js提供了自己独特的API,比如全局对象,带有当前进程信息的进程对象,操作文件的fs模块,创建Web服务的http模块等等。这些API使我们能够使用JavaScript来操作计算机,因此我们可以使用Node.js平台来开发web服务器。还有一些Node.js和浏览器共享的对象,比如JavaScript引擎的内置对象,都是V8引擎提供的。常见的有:

undefined、null、NaN、Infinity的基本常数;内置对象布尔、数字、字符串、对象、符号、函数、数组、正则表达式、集合、映射、承诺、代理;全局函数eval、encodeURIComponent、decodeURIComponent等等。另外,还有一些方法不属于引擎内置的API,但两者都可以实现,比如setTimeout、setInterval方法、Console对象等等。

5.1阻塞IO和非阻塞IO如果我们想在程序中对一个文件进行操作,那么我们需要打开文件:通过文件描述符。我们想:JavaScript可以直接操作一个文件吗?看似可能,但实际上我们任何程序中的文件操作都需要系统调用(操作系统的文件系统);实际上,对文件的操作就是一个操作系统的IO操作(输入输出)。操作系统为我们提供了阻塞调用和非阻塞调用:

阻塞调用:在调用结果返回之前,当前线程处于阻塞状态(阻塞状态的CPU不会分配时间芯片),调用线程只有在获得调用结果后才会继续执行。非阻塞调用:调用执行后,当前线程不会停止执行,只需要一段时间检查是否返回结果。所以我们开发中很多耗时的操作都可以基于这样的非阻塞调用:比如网络请求本身使用Socket通信,Socket本身提供select模型,可以以非阻塞的方式工作;比如读写文件的IO操作,我们可以使用操作系统提供的基于事件的回调机制。

5.2非阻塞IO的问题,但是非阻塞IO会有一些问题:我们还没有得到需要读取的结果(以读取为例),这意味着为了知道我们是否读取了完整的数据,我们需要频繁地确定读取的数据是否完整。这个过程叫做轮换训练操作。那么谁来完成轮训这个工作呢?如果我们的主线程频繁的做轮换训练,性能会大大降低,而且在开发中,我们可能不止读写一个文件,可能有多个文件,可能有多个函数:网络IO,数据库IO,子进程调用。Libuv提供了一个线程池:线程池会负责所有相关的操作,会通过轮换训练等方式等待结果。当获得结果时,相应的回调可以放在事件循环中(一个事件队列)。循环可以接管后续的回调工作,并告诉JavaScript应用程序执行相应的回调函数。

5.3阻塞与非阻塞、同步与异步的区别?第一,屏蔽和非屏蔽是针对被叫方的;这是系统调用。操作系统为我们提供了阻塞调用和非阻塞调用。同步和异步是针对调用者的。

这是我们自己的程序;如果发起调用后我们除了等待结果什么都不做,这个过程就叫同步调用;如果我们重新开始调用,就不会等待结果,继续完成其他工作,等到有回调的时候再执行。这个过程就是异步调用。Libuv采用非阻塞异步IO的调用方式。

5.4节点事件循环(Node event loop)的阶段,我们前面强调过,就像一个桥梁,是应用的JavaScript和系统调用之间的通道:我们的文件IO、数据库、网络IO、定时器、子进程在完成相应的操作后,会把相应的结果和回调函数放到事件循环(任务队列)中;循环将不断地从任务队列中取出相应的事件(回调函数)来执行;但是一个完整的事件周期分笔成交点分为许多阶段:

计时器:这个阶段执行由setTimeout()和setInterval()设置的预定回调函数。挂起回调:回调一些系统操作(比如TCP错误类型),比如TCP连接时接收idle,准备:只在系统内部使用。轮询:检索新的I/O事件;执行与I/O相关的回调;检测:setImmediate()回调函数在这里执行。封闭式回调函数:一些封闭式回调函数,比如socket.on('close '),).

5.5节点事件周期的阶段图

极客用语

06

Node.js的通用内置模块和全局变量

有关全局对象的更多信息,请参考以下链接:https://m.runoob.com/nodejs/nodejs-global-object.html.

作者:糖果糖果来源:微信微信官方账号:百度极客说来源:https://mp.weixin.qq.com/s/QI9l4kKCbJxifNZt3QP3Lg

为您推荐

常用但是不常见的电脑快捷键(二)

常用的电脑快捷键其实有非常多,但是我们一般知道的都不是很多,下面就一起来看看这些你可能不知道的电脑快捷键。1、Win+← \ → 使正在使用中的窗口贴向屏幕左侧/右侧,而只占用50% 的显示器面积,熟练使用此功能对同时编辑两个文档并进行校对

2023-01-07 16:35

什么是web3.0?普通人怎么去介入呢?

首先我们先从Web1.0开始说起,指的是互联网的早期阶段,特点是网站静态、单向信息传递,用户只能浏览网站内容而不能交互,在这个阶段,网站的内容主要由专业人员维护,用户无法对网站内容进行修改或更新,随着互联网的发展,Web1.0已经逐渐淡出历

2023-01-07 16:32

河北省教育考试院最新公告查询(河北省教育考试院最新发布)

省教育考试院最新发布2022年河北省成人高校招生报名公告↓↓↓按照教育部工作部署,2022年河北省成人高校招生报名工作即将开始,现将有关事项公告如下:一、报名方式我省成人高校招生报名工作实行网上报名、网上审核、网上交费。考生在规定时间内,登

2023-01-07 16:30

河北师范大学招生信息网(汉语言文字学考研真题)

各位学弟学妹大家好,我是2020年河北师范大学汉语言文字学的考生,初试成绩:总分389分,在这里分享给大家我的经验,希望对你们有所帮助。一、题主背景本科是河北师大,在大三下学期我们顶岗实习,6月底回来后一直不确定考研,7月份确定考研,虽然本

2023-01-07 16:26

哲学考研丨河北师范大学:招生情况、参考书、分数线和录取数据

考研择校要考虑的方面实在太多,需要你自己尽力抓取有用的信息,结合自己的情况,慎重做出选择。今天,研新生给大家带来河北师范大学哲学学硕择校分析,希望对大家有所帮助!河北师范大学01、院校概况河北师范大学(Hebei Normal Univer

2023-01-07 16:23

河北师范大学在职研究生招生简章2022(河北师范大学博士招生简章2023)

【时代空乘】——河北师范大学空乘专业招生简章河北师范大学旅游管理专业(校企合作培养)学制四年。学生学习期满成绩合格者,由河北师范大学颁发普通高等学校本科毕业证书,符合授予学位条件的授予管理学学士学位。该专业培养具有良好政治素质、文化素质、专

2023-01-07 16:20

加载中...