Node.js01--零散总结

Node.js笔记(七)————零散总结

模块

net模块包含了Node需要的所有TCP功能。用net.createServer()方法创建一个新的TCP服务端。
Express模块是合同谈判模块的扩展。Express、net、http都是用Server()创建服务器,并用listen()来监听指定窗口。
Express会在后台调用http模块,Express增加了亮相http模块没有的功能:根据HTTP请求的不同方法进行过滤;根据特定的URL进行过滤。

采用HTTP模块时,需要创建HTTP头,res.writeHead,并且在发送请求内容之前把HTTP头先发送给客户端。Express提供了一个方便的方法,res.(http:response)对象的send()方法。此方法发送HTTP头,同时还会调用response.end()方法。如果给res.send()传递一个对象,它会自动把其序列化为JSON并添加对应的HTTP头。

http模块并非只包含了HTTP服务端的功能,它同时还提供了客户端的功能。用http.request()工厂方法来创建新的http请求对象。接受两个参数:第一个参数是config对象,第二个参数是回调函数。回调函数是监听在http.request的response事件上的。在Express服务器中,我们用了express.bodyDecoder来处理请求数据流中所有的内容,但在客户端我们只能手动处理流数据。只有当我们把服务器返回的数据接收完整后,end事件才会被触发。

Node是单线程的,但是CPU处理器是多核处理器,我们可以利用cluster模块把任务分配给子进程,就是说Node把当前程序复制了一份给另一个进程。当用cluster把工作共享到一组复制的Node程序时,主进程不会参与到每个具体的事务中。主进程管理所有的子进程,但当子进程与I/O交互时,它是直接进行操作的,不需要通过主进程。如果用cluster来创建一个Web服务器,请求将不会通过主进程,而是直接连接到子进程。cluster的工作原理是每一个Node进程要么是主进程,要么是工作进程。cluster提供了跨平台时让多个进程共享socket的方法。即使多个子进程在共享一个端口上的连接,其中一个堵塞了,也不hi影响其他工作进程的新连接。

因为EventEmitter是接口,从其继承的类需要使用new关键字来构造。

HTTP服务器中,connection和close时间表示了与客户端的TCP连接与关闭。request、checkContinue、upgrade和clientError事件是关联在HTTP请求上的。每个流指挥触发connection时间一次。

在HTTP客户端,应该使用http.ClientRequest类。需要配置(options)对象来创建一个http.ClientRequest实例,就是调用http.request()这个工厂方法,并传入options对象和回调函数。

http.get可以和http.request()做同样的事情(GET请求),但是在request中我们把method属性从配置中去掉了,还把request.end()也移除了。

每当调用ClientRequest.write()时,数据会马上上传(不会被缓存),但服务器在ClientRequest.end()调用之前是不会响应数据请求的。

URL

URL模块提供了3个方法:parse(解析)、format、resolve。

querystring模块是用来处理query字符串的简单辅助模块。它的主要功能有parse和decode。如果有一个query字符串,可以用parse把它转换成对象。需注意:数字是返回成字符串的,并非数字类型;传入的query字符串不能包含URL中标记的?。

querystring也被URL模块用作辅助模块。特别是在解析YRL时候可以指定URL模块把query字符串转换成对象返回。

一旦把内容复制到一个Buffer后,它就会以二进制的形式存储起来。一个UTF字符可能会占用最多4个字节。创建Buffer可以使用三个参数:指定Buffer的字节长度,需要拷贝到Buffer里的字节数组,或是需要拷贝到Buffer李的字符串。

Buffer.byteLength()方法获得字符串在编码上的字节长度,而不是String.length返回的字符个数。

Buffer.write()会把字符串写道Buffer指定的位置上。

DNS模块提供了用域名来代替IP地址作为事物的引用名称功能。主要有两个方法resolve()和reverse(),前者把域名转换成DNS记录,后者将IP地址转换成域名。

在哈希中使用数据时,可以调用hash.update()来生成数据摘要。要把哈希输出,只需要调用hash.digest()方法,这个方法会把所有通过hash.update()输入的数据生成摘要并输出。

process

process模块是全局的。因为任何时候否能使用process,所以process.stdin也会为所有的Node进程初始化。在尝试从stdin读数据之前,需要先调用它的resume()方法。

process.nextTick()创建了一个回调函数,它会在下一个tick或者时间循环下一次迭代时被调用。因为实现是使用队列的,所以它会取代其他事件。

用child_process模块来为Node主进程创建子进程。主要有两个方法:spawn()会创建一个子进程,并且会有独立的stdin、stdout和stderr文件描述符;exec()会创建子进程,并会在进程结束的时候以回调函数的方式返回结果。

assert

assert是为测试代码提供基础功能的核心库。它的很多方法都是成对出现的,一个提供正面的测试,另一个提供反面的功能。比如:equal()和notEqual(),接受两个参数,第一个是期待的值,第二个是实际的值。它们会检查相等(==)和不相等(!=)操作。在比较的时候会进行类型转换。strictEqual()和notStrictEqual()方法检测两个数值是否相等时会采用===和!==。assert.ok()方法是用来测试一个对象是否为真值的渐变方法,它会使用==来对比测试对象和true是否一样。deepEqual()和notDeepEqual()方法提供了深入比较两个对象值的方法。这些方法会进行若干测试,而无需太多的细节。如果任何一个检查失败了,测试就会抛出异常。首先用===检查他们是否相等,然后检查他们的类型是否是Buffer,如果是就检查它们的长度,然后按字节对比。如果对象的类型按==运算符不匹配,它们就不可能相等,最后如果比较的参数是对象类型,就会进行更加严格的测试,如比较两个对象的原型、属性数量,然后对每个属性执行deepEqual()进行递归比较。
assert方法的throws和doesNotThrow(),会检查指定的代码块是否会抛出异常。

虚拟模块

虚拟机模块(vm)可以让我们运行任意一块代码,并得到运行结果。它提供了一些功能可以修改指定代码运行的上下文。用vm运行有两个方法,第一种与使用eval()方法类似,把代码内嵌运行,第二种先把代码预编译成vm.script对象。
第一种:

1
2
3
> var vm=require(‘vm’);
> vm.runInThisContext(‘1+1’);
2

跟eval()方法很像,我们给它传入一段代码,就返回结果。但是vm并不会像eval()那样改变本地作用域的内容。eval()会修改周围的上下文,但vm不会。
例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
> var vm=require('vm'),
e=0,
v=0;
> eval(e=e+1);
1
> e
1
1
2
3
4
5
6
> vm.runInThisContext('v=0');
0
>vm.runInThisContext('v=v+1');
1
> v
0

vm.runInNewContext(),用其第二个参数作为上下文对象,该对象的作用域就成了我们用vm运行代码的上下文。如果我们继续把它传给不同的调用,此上下文就会被修改。而且这个上下文能够被全局作用域使用。

连接池

生产环境通常由多种资源组成:Web服务器、缓存服务器和数据库服务器。数据库通常是部署在Web服务器之外的独立机器上,这使得面向公众的网站不必重新配置和修改复杂的数据库集群就可以垂直增长。建立一个数据库的连接的开销相对来说是很大的,为每个请求创建一个甚至多个连接会对高流量网站造成不必要的额外负担,也会导致性能下降。解决方案是在内部缓存池里维护数据库连接,当某链接不再需要时,它会被放回连接池里,这样就能立刻为下一个进入的请求服务了。当用户尝试获取一个连接时,如果没有已经打开的连接,连接池会调用创建函数。如果一个连接闲置太久了,它会被销毁并且释放内存资源。

消息队列协议

造成堵塞的原因有很多,可能是因为在注册过程中需要发送用户邮件,需要对用户输入进行大量的数学运算,或者是某个任务需要花费的时间超过了用户期望的等待时间等等。Node的事件驱动设计可以用来应对大多情况,它采用的是异步函数和回调函数的方法。但是如果一个时间特别“重”的话,就不应该放在Node内部处理,Node应该只负责快速运算和处理返回的结果。消息队列允许程序员发布事件然后继续其他操作,通过进程间通信频道,提高了并发处理的效率,并实现了更高的扩展性。工作队列的工作原理就是发布的消息在连接到队列的客户端间循环触发。

Express

路由是按顺序执行的。当多个路由同时匹配上提供的URL时,只有第一个匹配的路由会执行相关的动作,也就是说如何安排路由的顺序是非常重要的。

中间件

中间件是一小段特定的代码,位于原始请求时间与指定的路由之间。我们通过中间件对一些通用功能进行代码宠用,如用户授权或log记录。中间件在传递的过程中,不仅把状态传递过去,还包括了跟状态交互的方法。中间件的形式:function(req,res,next)。在实际工作中,中间件好比家里或办公室里看得见的电话线,所有电话(应用)都连接到电话线(中间件)上,而后者能把应用与对应底层的网络连接起来。

-------------本文结束感谢您的阅读-------------