手机版

Nodejs研究笔记的全局对象

时间:2021-10-15 来源:互联网 编辑:宝哥软件园 浏览:

一、开篇分析。

在最后一章中,我们学习了NodeJS的基本理论知识,对于它的理解是非常重要的。在接下来的章节中,我们将根据官方文件逐步学习模块的各个部分。好了,这篇文章的主角该登场了,环球。

让我们看看官方的定义:

全局对象全局对象它们在所有模块中都可用。其中一些对象实际上不在全局范围内,而是在模块范围内——这一点将被记住。

这些对象在所有模块中都可用。实际上,有些对象不在全局范围内,而是在它的模块范围内——这些将被识别。

在浏览器中,顶级范围是全局范围。这意味着在浏览器中,如果你在全局范围内,某些东西会定义一个全局变量。

在节点中,这是不同的。顶层范围不是全局范围;节点模块内部变量将是该模块的本地变量。

我不认为每个人都应该不熟悉全局对象的概念。在浏览器中,最高级别的作用域是全局作用域,这意味着如果使用“var”在全局作用域中定义变量,该变量将被定义为全局作用域。

但是在NodeJS中就不一样了。最高级别的范围不是全局范围。在模块中,变量由“var”定义,并且该变量仅在该模块的范围内。

在NodeJS中,模块中定义的变量、函数或方法只在模块中可用,但是可以使用exports对象将它们传递到模块外部。

但是Node.js中还是有全局作用域的,就是可以定义一些不用加载任何模块就可以使用的变量、函数或者类。

同时,预定义了一些全局方法和全局类。全局对象是NodeJS中的全局命名空间,任何全局变量、函数或对象都是这个对象的属性值。

在REPL运行环境中,您可以通过以下语句观察全局对象中的详细信息,如下图所示:

我将逐一介绍安装在全局对象上的相关属性值对象。

(1)、过程

进程{对象}进程对象。请参见过程对象部分。

进程{对象}这是一个进程对象。我将在接下来的章节中详细说明它,但这里我将首先向您展示一个api。

process.nextTick(回调)

在事件循环的下一个循环中,调用此回调。这不是setTimeout(fn,0)的简单别名,它要高效得多。它通常在任何其他输入/输出事件触发之前运行,但也有一些例外。请参见下面的process.maxTickDepth。

在事件循环的下一个循环中调用回调函数。这不是setTimeout(fn,0)函数的简单别名,因为它的效率要高得多。

这个函数可以在任何I/O之前调用我们的回调函数,如果你想在对象创建之后、I/O操作发生之前执行一些操作,这个函数对你来说非常重要。

很多人不理解Node.js中process.nextTick()的用法,我们来看看什么是process.nextTick()以及如何使用。

Node.js是单线程的。除了系统IO,在其事件轮询过程中,同一时间只会处理一个事件。您可以将事件轮询视为一个大队列,在每个时间点,系统将只处理一个事件。

即使您的计算机有多个CPU内核,您也不能并行处理多个事件。但是正是这个特性使得node.js适合I/O类型的应用,而不适合CPU类型的应用。

在每个I/O应用程序中,只需要为每个输入输出定义一个回调函数,它们就会被自动添加到事件轮询的处理队列中。

当输入/输出操作完成时,将触发该回调函数。然后系统将继续处理其他请求。

在这种处理模式下,process.nextTick()的含义是定义一个动作,并让这个动作在下一个事件轮询的时间点执行。我们来看一个例子。示例有一个foo(),您希望在下一个时间点调用它,您可以这样做:

复制代码如下: function foo(){ console . error(' foo ');} process . NextTick(foo);console . error(' bar ');

运行上面的代码,你会从下面终端打印的信息中看到‘bar’的输出在“foo”前面。这验证了上面的声明,即foo()正在下一个时间点运行。

复制代码如下:barfoo。

您也可以使用setTimeout()函数来实现看似相同的执行效果:

复制代码如下:setTimeout(foo,0);console . log(' bar ');

但是,在内部处理机制上,process.nextTick()和setTimeout(fn,0)是不同的。process.nextTick()不是简单的延迟,而是有更多的特性。

更准确地说,process.nextTick()定义的调用将创建一个新的子堆栈。在当前堆栈中,您可以执行任意数量的操作。但是一旦调用了netxTick,函数就必须返回到父栈。然后,事件轮询机制再次等待处理新的事件,如果找到nextTick的调用,将创建一个新的堆栈。

让我们看看什么时候使用process.nextTick():

在多个事件中交叉执行CPU密集型任务;

在下面的示例中,有一个compute(),我们希望尽可能连续地执行该函数,以执行一些计算密集型任务。

不过,同时我们也希望系统不会被这个功能屏蔽,还需要能够对其他事件做出响应。应用程序模式就像一个单线程web服务服务器。在这里,我们可以使用process.nextTick()来交叉执行compute()和正常事件响应。

复制代码如下: var http=require(' http ');function compute() {//连续执行复杂的计算/.process.nextTick(计算);}http.createServer(函数(req,res) {res.writeHead(200,{ ' Content-Type ' : ' text/plain ' });RES . end(' Hello World ');}).听(5000,' 127 . 0 . 0 . 1 ');compute();

在这种模式下,我们不需要递归调用compute(),只需要在事件循环中使用process.nextTick()定义compute()在下一个时间点执行即可。

在这个过程中,如果有新的http请求进来,事件循环机制将首先处理新的请求,然后调用compute()。

相反,如果将compute()放在递归调用中,系统将一直被阻塞在compute()中,无法处理新的http请求。你可以自己试试。

当然,我们无法通过process.nextTick()得到多CPU下并行执行的真正好处,只是模拟同一个应用在CPU上分段执行。

(2)、控制台

控制台{对象}用于打印到标准输出和标准错误。参见stdio部分。

控制台{object}用于打印到标准输出和错误输出。请参见以下测试:

复制代码如下: console . log(' Hello bigbar!'。) ;for(控制台中的var I){ console . log(I ' ' console[I]);}

获得以下输出结果:

复制代码如下: varlog=function(){ process . stdout . write(format . apply(this,arguments)' \ n ');} var info=function(){ process . stdout . write(format . apply(this,arguments)' \ n ');} var warn=function(){ WriteError(format . apply(this,arguments)' \ n ');} var error=function(){ write error(format . apply(this,arguments)' \ n ');} var dir=function(object){ var util=require(' util ');process . stdout . write(util . inspect(object)' \ n ');} var time=function(label){ times[label]=date . now();} var timeEnd=function(label){ var duration=date . now()-times[label];exports . log(' undefined : NAMs ',标签,持续时间);} var trace=function(label){//TODO一旦//被公开,可能可以用V8的debug对象更好地做到这一点。var err=新错误;err.name=' Traceerr.message=label | |Error.captureStackTrace(err,arguments . caller);console . error(err . stack);} var assert=function(expression){ if(!表达式){ var arr=array . prototype . slice . call(参数,1);需要(' assert ')。ok(false,format.apply(this,arr));}}

通过这些函数,我们基本上知道NodeJS给全局范围增加了什么。事实上,控制台对象上的相关api只在更高级别的Process对象上封装“stdout.write”,并将其挂在全局对象上。

(3)、出口和模块出口

在NodeJS中,有两个作用域,分为全局作用域和模块作用域。

复制代码如下: var name=' var-name ';name=' nameglobal . name=' global-name ';this.name=“模块名”;console . log(global . name);console . log(this . name);console.log(名称);

我们看到var name=' var-name ';name=' name是一个已定义的局部变量;

和global . name=' global-name ';是为全局对象定义名称属性,

和this . name=' module-name ';为模块对象定义了名称属性。

让我们验证一下,将以下内容保存为test2.js并运行它。

复制代码如下:var t1=require('。/test1’);console . log(t1 . name);console . log(global . name);

从结果中可以看出,我们成功导入了test1模块并运行了test1的代码,因为global.name是在test2中输出的。

而t1.name是由test1模块中的this.name定义的,表示这是指模块作用域对象。

出口和模块出口的区别

Module.exportss是真正的接口,export只是一个辅助工具。模块导出最终返回调用,而不是导出。

通过导出收集的所有属性和方法都分配给模块。当然,这是以Module.exports本身没有任何属性或方法为前提的。

如果Module.exports已经有一些属性和方法,那么通过导出收集的信息将被忽略。

举个栗子:

创建一个新文件bb.js

复制代码如下: exports . name=function(){ console . log('我叫大熊!'。) ;} ;

创建一个测试文件test.js

复制代码如下:var bb=require('。/bb . js ');bb . name();//“我叫大熊!”

修改bb.js如下:

复制代码如下:module.exports='BigBear!'。exports . name=function(){ console . log('我叫大熊!') ;} ;

再次引用执行bb.js。

复制代码如下:var bb=require('。/bb . js ');bb . name();//没有方法“名称”

因此,您的模块不必返回“实例化对象”。您的模块可以是任何合法的javascript对象——布尔、数字、日期、JSON、字符串、函数、数组等等。

(4)、setTimeout、setInterval、process.nextTick、setImmediate

以下内容以摘要的形式出现。

Nodejs的特点是事件驱动,异步I/O的高并发性,产生这一特性的引擎是事件循环,将事件分类为对应的事件观察器,如空闲观察器、定时器观察器、I/O观察器等。事件循环的每个周期称为Tick,每个Tick从事件观察器中取出事件进行顺序处理。

在调用setTimeout()或setInterval()时创建的计时器将被放入计时器观察器内部的红黑树中,每次进行Tick时,都会从红黑树中检查计时器是否超过了计时时间,如果超过,则立即执行相应的回调函数。当使用定时器时,使用SetTimeout()和setInterval()。它们的区别在于后者是反复触发的,由于时间设置的太短,在前一次触发完成后,处理完毕后会立即触发。

因为定时器是超时触发的,所以触发精度会降低。例如,setTimeout设置的超时时间为5秒。当事件循环在第4秒到达一个任务,其执行时间为3秒时,setTimeout的回调函数会逾期2秒执行,这就是准确率降低的原因。此外,采用红黑树和迭代法来节省定时器和判断触发器,浪费了性能。

使用process.nextTick()设置的所有回调函数都将被放入数组中,所有回调函数都将在下一个Tick中立即执行。该操作重量轻,时间精度高。

setImmediate()设置的回调函数也在下一个Tick调用,这与process.nextTick()有两点不同:

1、它们所属的观察者优先级不同,process.nextTick()属于空闲观察者,setImmediate()属于检查观察者,空闲的优先级是检查。

2.setImmediate()设置的回调函数放在链表中,每个Tick在链表中只执行一次回调。这是为了确保每个Tick都能快速执行。

二、总结。

1、理解全局对象存在的意义。

出口和模块出口有一点区别

3.构建的Console底层是什么(Process对象的高层封装)?

4、setTimeout、setInterval、process.nextTick和setImmediate的区别。

5.NodeJS中的两个作用域。

版权声明:Nodejs研究笔记的全局对象是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。