异步 I/O
在Node
中,绝大多数的操作都是以异步的方式进行调用。 这样的意义在于:在Node
中,我们可以从语言层面很自然地进行并行I/O
操作。
每个调用之间无须等待之前的I/O
调用结束,极大提高了效率。
举例:
var fs = require('fs');
fs.readFile('/path', function (err, file){
console.log ('Well Done!')
});
console.log('Calling for file!');
"Well Done!"
是在"Calling for file!"
之后输入的。
事件与回调函数
无论在前端和后端,事件都是常用的。
var http = require('http');
var querystring = require('querystring');
//侦听服务器的request事件
http.createServer(function(req, res){
var postData = '';
req.setEncoding('utf8');
//侦听请求的data事件
req.on('data', function (trunk){
postData += trunk;
});
//侦听请求的end事件
req.on('end', function(){
res.end(postData);
});
}).listen(8080);
console.log('服务器启动完成!')
Node
创建了一个Web
服务器,并侦听8080
端口。对于服务器,为其绑定了request
事件,对于请求对象,我们为其绑定了data
事件和end
事件。
相应地,我们在前端为Ajax
请求绑定了success
事件,在发出请求后,只需关心请求成功时执行相应的业务逻辑即可。
$.ajax({
'url': '/url',
'method': 'POST',
'data': {},
'success': function (data){
// success事件
}
});
除了事件外,回调函数也无处不在。但是,回调函数也是最好的接收异步调用返回数据的方式。
单线程
在Node
中,javascript
与其余线程是无法共享任何状态的。
单线程的最好好处是不用像多线程那样要在意状态的同步问题,没有死锁的存在,也没有线程上下文交换所带来的性能上的开销。
缺点也是有的:
- 无法利用多核
CPU
- 错误会引起整个应用的退出,健壮性问题
- 大量计算占用
CPU
导致无法继续调用异步I/O
Node
采用子进程来解决单线程中大计算量的问题: chile_process
。
朴灵. 深入浅出Node.js[M]. 人民邮电出版社, 2013.