首页 > 代码库 > nodejs(二) --- 重要知识点回顾

nodejs(二) --- 重要知识点回顾

1. 运行一个nodejs文件

如一个js文件中只含有console.log("hello world");的文件,我们再git里运行node,即 node hello.js 即可发送输出hello world。如下:

技术分享

 

2. 交互模式

直接输入node,即进入node环境,即可输入任何语句

技术分享

 

 

3. 创建一个简单的服务器

创建server.js -> require http模块 -> 调用 createServer 方法进行创建 -> 监听某个端口 -> 运行js文件(实际上是在运行这个node服务器) -> 在浏览器中发送请求。

js文件如下:

技术分享

其中比较重要的是要知道createServer这个内置函数就是用于创建服务器的,然后接受一个函数作为参数,我们可以用writeHead方法来写头部,使用end方法来输出内容。用listen来监听端口号。当然,也可以是监听8889等端口号,只要是合法的就行。在浏览器端发出请求,结果如下:

技术分享

 

 

4. node中的npm

 

安装node时就已经安装了npm,即一个包管理工具,我们一般利用它来安装一些包,即npm install <package> 如果后面添加 -g ,那么就会将包安全到全局环境,即user路径下。如果不添加,就会安装在当前文件夹下,当然首先会创建node_modules文件,在此之下。

 

一般,我们要创建一个项目时,我们可以先npm init,通过它,我们就可以创建一个package.json文件,然后通过配置该文件说明我们的项目信息。其中主要的参数有:

(1)name --- 包名   (2)version --- 版本号  (3) description --- 包的描述   (4) homepage --- 包的官网url  (5) author --- 包的作者名字  (6) contributors --- 包的其他贡献者名字

(7)dependencies  --- 依赖包列表(如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下)    (8)repository --- 包代码存放的地方   (9)main --- main 字段是一个模块ID,它是一个指向你程序的主要项目。就是说,如果你包的名字叫 express,然后用户安装它,然后require("express")    (9) keywords --- 关键字

 

卸载模块: npm uninstall <package>

 

更新模块: npm update <package>

 

版本号相关: 当使用npm下载和发布代码时,都会涉及到版本号相关,即X-Y-Z,一般而言,只有当版本发生了重大的变化,不向下兼容时,X才会变化; 如果增加了新的功能,仍旧向下兼容 Y 发生变化; 如果仅仅是做了很小的改变,如修复了bug,那么 Z 发生变化。

 

如果希望知道某条命令的详细信息,如install的,可以输入 npm help install

 

npm连接的是国外的网站,也可以使用淘宝镜像:

npm install -g cnpm --registry=https://registry.npm.taobao.org

 然后就可以使用cnpm来安装了。

 

 

5. nodejs REPL

即node的交互式解释器,即我们输入node之后即进入node环境,这个node环境就是node的交互式解释器。

值得注意的是,和console控制台不同,REPL支持多行输入,如下所示:

$ node> var x = 0undefined> do {... x++;... console.log("x: " + x);... } while ( x < 5 );x: 1x: 2x: 3x: 4x: 5undefined>

一般我们使用ctrl + c来退出该环境,大多数情况下,我们都是用ctrl+c来退出环境的。不论是否是node。

 

 

6. nodejs回调函数

在node中,我们知道其最大的特点就是异步I/O,而实现异步I/O的关键就在于回调函数。

首先,我们看看同步的是什么样:

var fs = require("fs");var data = http://www.mamicode.com/fs.readFileSync(test.txt);console.log(data.toString());console.log("over");

这是main.js中的代码,即先引入fs模块,然后才能实用相应的API,readFileAsync()函数用于同步读取文件,它是阻塞的,返回这个读取的文件,输出如下:

技术分享

 

下面这个一个异步的,

    var fs = require("fs");    fs.readFile("test.txt",function (err, data) {        if (err) {            console.log(err);        } else {            console.log(data.toString());        }    });    console.log("over");

结果如下:

技术分享

即readFile是一个异步的,在执行这条语句的时候不会阻塞后面的语句,而是在读完文件之后再console。

即我们在读取代码的时候可以做下面的很多事情,这样就可以节省很多时间。

注意node是单进程和单线程的,所以这里怎么理解呢?

 

7. nodejs事件循环

nodejs事件循环利用的是观察者模式,也就是发布订阅模式。简单的理解,DOM元素绑定事件就是这样的模式。其中绑定的元素是发布者,函数是订阅者,当元素发生了变化时(被点击等),就会通知所有的订阅者。 

nodejs使用事件驱动模型,当服务器接受到了请求之后,就会关闭这个请求,然后再处理,为的是等待下一个请求。这样,请求就不会被耽搁。这个模型的效率非常高,因为他一直在接受请求,而没有等待任何读写操作。在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数:

技术分享

虽然这里没有所谓的DOM元素,但是实现应当是一样的,即观察者模式的最好理解是好莱坞电影中的一句话: 你不要打电话给我,我会打电话给你

在node中我们常常使用events模块来实现,即首先引入events,然后创建一个对象,利用这个对象的on方法绑定时间,利用对象的emit方法来触发事件,如下所示:

var events = require("events");var eventEmitter = new events.EventEmitter();eventEmitter.on("selfDefine", function () {    console.log("This is selfDefine1");});eventEmitter.on("selfDefine", function () {    console.log("This is selfDefine2");});eventEmitter.on("selfDefine", function () {    console.log("This is selfDefine3");});eventEmitter.on("selfDefine", function () {    console.log("This is selfDefine4");});eventEmitter.emit("selfDefine");console.log("over");

最终效果如下:

技术分享

在这里,我们就可以认为这是发布订阅者模式,首先可以知道发布者是selfDefine事件,订阅者是4个,一旦selfDefine被触发,那么就会通知订阅者,方法是将订阅者添加到了Event Loop中去,然后通过事件循环来监听,一旦被触发,就会通知,即我给你打电话,你没有给我打电话。

当事件触发时,注册到这个事件的事件监听器被依次调用。

 

另外,在on和emit中是可以传递参数的,如下所示:

var events = require("events");var eventEmitter = new events.EventEmitter();eventEmitter.on("selfDefine", function (x) {    console.log("This is selfDefine1 " + x);});eventEmitter.on("selfDefine", function (x) {    console.log("This is selfDefine2 " + x);});eventEmitter.on("selfDefine", function (x) {    console.log("This is selfDefine3 " + x);});eventEmitter.on("selfDefine", function (x) {    console.log("This is selfDefine4 " + x);});eventEmitter.emit("selfDefine", "argument");console.log("over");

最终的效果如下:

技术分享

 

 

关于 EventEmitter 还有其他的属性,如下所示:

addListener(event, listener) --- 它和on是类似的,都是添加某一个事件的监听器

removeListener(event, listener) --- 即通过此API可以将监听器取消(特定的listener)。

removeAllListeners(event) --- 可以取消event下的所有监听器。

newListener(event, listener); --- 该事件在添加新的监听器时被触发。

listenerCount(emitter, event); --- 返回指定监听器的数量。

listeners(event) --- 返回指定事件的监听器数组。

 

once(event, listener) --- 通过once就可以知道,这个监听器只会监听一次,后面再调用,就不会监听了。

举例如下:

var events = require("events");var eventEmitter = new events.EventEmitter();eventEmitter.on("foo", function () {    console.log("via on");});eventEmitter.once("foo", function () {    console.log("via once");});eventEmitter.emit("foo");setTimeout(function () {    eventEmitter.emit("foo");}, 1000);

 

最终的执行效果如下:

技术分享

在执行过程中vai on和via once是同时出现的,过了1s之后,via on 出现, via once不再出现,因为通过once添加的监听器只会监听一次,然后就被销毁了(即后面不再监听)。

 

 

 

 

8. Nodejs Buffer (缓冲区)

作为服务器端语言的nodejs,自然会接受请求,如TCP请求,都是通过二进制来传递的,但是js语言本身并没有接受二进制的api,所以nodejs中添加了Buffer类来作为存储二进制数据的缓冲区。

通过Buffer类创建buffer实例的几种方法:
1. 创建长度为10字节(1 B = 8 bit)的Buffer类, var buf = new Buffer(10);

2. 通过数组创建Buffer实例, var buf = new Buffer([10, 20, 30, 15]);

3. 通过一个字符串来创建buffer实例, var buf = new Buffer("i love coding", "utf-8"); 注意: 我们这里使用utf-8格式编码,还可以是"ascii",  "utf16le", "ucs2", "base64" 和 "hex",当然,默认就是utf-8。

已经有了buffer实例,我们就可以使用buffer实例的一些方法了,如下所示:

  • write()(写入数据) --- buf.write(string[, offset[, length]][, encoding])。它的返回值是写入的长度。  我们知道[]表示式可选的, 其中string是将要写入的字符串; offset是缓冲区开始写入的索引值,默认为0;length是长度,默认是buf.length; encoding是编码方式,默认是utf-8。
  • toString() (读取数据)--- buf.toString([encoding[, start[, end]]])。它的返回值是读取的值。其中的encoding表示读取数据的编码方式, start和end表示读取数据的位置。
  • toJSON() (转换为JSON对象)--- buf.toJSON(buf)。 返回值是一个JSON对象。
  • Buffer.concat(list[,totalLength]) (合并Buffer对象) --- 返回值是合并后的buffer对象。其中list是一个数组,其中的每个元素是一个buffer实例,totalLength是在制定合并之后的总长度。
  • buf.compare(otherBuffer) (缓冲区大小比较) ---  比较两个缓冲区的大小,返回 0 -1 1 。
  • buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]]) (缓冲区的拷贝
  • buf.slice([start[, end]])(缓冲区的裁剪)
  • buf.length() --- 返回缓冲区的长度。
  • ......

 

9. Nodejs Stream(流)

 

nodejs(二) --- 重要知识点回顾