参考内容:
Node.js REPL(交互式解释器)
C/C++之回调函数
注意 - 在nodejs网页中使用中文时需要保证两点
- .js文件以UTF8格式保存;
- 在HTML Head中需要设置charset=utf-8,如使用
response.writeHead(200, {'Content-Type':'text/html;charset=utf-8'});
进行设置。
一、Node.js REPL(交互式解释器)
Node的交互式解释器可以很好地调试Javascript代码
- 启动Node终端
$ node
>
- 简单表达式运算
$ node
> 1+4
5
> 5/2
2.5
> 3*6
18
> 4-1
3
> 1+(2*3)-4
3
>
- 使用变量
变量声明使用var关键字,如果没有使用var关键字,变量会直接打印出来;使用var关键字的变量,可以使用console.log()输出。
$ node
> x = 10
10
> var y = 10
undefined
> x + y
20
> console.log("Hello World")
Hello World
undefined
> console.log(y)
10
undefined
>
- 多行表达式
类似JavaScript,执行一个do-while循环。...系统自动生成,Node自动检测是否为连续表达式。
$ node
> var x = 0
undefined
> do {
... x ++;
... console.log("x: " + x);
... } while (x < 5);
x: 1
x: 2
x: 3
x: 4
x: 5
undefined
>
- 下划线(_)变量
可以使用下划线获取表达式的运算结果。
$ node
> var x = 10
undefined
> var y = 20
undefined
> x + y
30
> var sum = _
undefined
> console.log(sum)
30
undefined
>
REPL命令
ctrl + c #退出当前终端
ctrl + c按下两次 #退出Node REPL
ctrl + d #退出Node REPL
向上/向下 键 #查看输入的历史命令
tab 键 #列出当前命令
.help #列出使用命令
.break #退出多行表达式
.clear #退出多行表达式
.save filename #保存当前的Node REPL会话到指定文件
.load filename #载入当前Node REPL会话的文件内容
二、Node.js回调函数
Node.js异步编程直接体现就是回调。回调函数在完成任务后会被调用,Node使用了大量的回调函数,所有API都支持回调函数。
阻塞代码实例
- 创建一个1.2.input.txt文本,内容如下(注意需要使用UTF8编码格式保存,否则会中文乱码):
Hello, I'm input.txt!这是一个Input.txt文件!
- 创建一个1.2.main.js文件,代码如下(同样以UTF8格式保存,我使用的编辑器是NotePad++,有修改编码格式的功能):
var fs = require("fs");
var data = fs.readFileSync('1.2.input.txt');
console.log(data.toString());
console.log("程序执行结束!");
-
执行以上代码,结果如下:
非阻塞代码实例
- 文本文件1.2.input.txt与之前相同;
- 修改1.2.main.js内容,如下:
var fs = require("fs");
fs.readFile('1.2.input.txt', function (err, data) {
if (err) return console.error(err);
console.log(data.toString());
});
console.log("程序执行结束!");
-
执行以上代码,结果如下:
可以看出非阻塞代码不需要等待文件读取完即可执行,不需要按照顺序进行,所以如果需要处理回调函数的参数,就需要写在回调函数内。
三、Node.js事件循环
- Node.js是单进程单线程应用程序,但通过事件和回调支持并发,所以性能高;
- Node.js的每一个API都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发;
- Node.js基本所有的事件机制都是用设计模式中的观察者模式实现;
- Node.js单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数。
事件驱动程序
Node.js使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后服务下一个web请求;
当这个请求完成,它被放回处理队列,当到达队列开头,结果被返回给用户;
web server一直接受请求而不等待任何读写操作(称之为非阻塞IO或事件驱动IO),在事件驱动模型中,会生成一个主循环监听事件,检测到事件时触发回调函数。
- Node.js有多个内置事件,可通过引入events模块,并通过实例化
EventEmitter 类来绑定和监听事件,如下:
// 引入events模块
var events = require('events');
// 创建eventEmitter对象
var eventEmitter = new events.EventEmitter();
以下绑定事件处理程序:
// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);
通过程序触发事件:
// 触发事件
eventEmitter.emit('eventName');
- 实例
创建1.3.1.main.js文件,代码如下:
// 引入events模块
var events = require('events');
// 创建eventEmitter对象
var eventEmitter = new events.EventEmitter();
// 创建事件处理程序
var connectHandler = function connected() {
console.log('连接成功。');
// 触发data_received事件
eventEmitter.emit('data_received');
}
// 绑定connection事件处理程序
eventEmitter.on('connection', connectHandler);
// 使用匿名函数绑定data_received事件
eventEmitter.on('data_received', function() {
console.log('数据接收成功。');
});
// 触发connection事件
eventEmitter.emit('connection');
console.log("程序执行完毕。");
Node应用程序的工作过程
在Node应用中,执行异步操作的函数将回调函数作为最后一个参数,回调函数接受错误对象作为第一个参数。
- 继续使用之前的1.2.input.txt文本文件;
- 创建1.3.2.main.js,内容如下:
var fs = require("fs");
fs.readFile('1.2.input.txt', function (err, data) {
if (err) {
console.log(err.stack);
return ;
}
console.log(data.toString());
});
console.log("程序执行完毕!");
以上程序fs.readFile()是异步函数用于读取文件。如果读取中发生错误,err对象会输出错误信息;如果不发生错误,文件内容通过回调函数输出。以上代码执行结果如下:
-
如果没有1.2.input.txt文件,执行结果如下,输出了错误信息: