Node.js的核心概念:非阻塞IO和异步编程。这个机制给Node.js带来了巨大的优势和好处,但同时它也带来了许多问题和挑战。
3.1 传统编程方式
如果有方法可以最大化利用CPU的计算能力和可用内存以减少资源浪费,那将再好不过了。而这,正式Node.js的精髓所在。
3.2 Node.js的编程方式
var fs = require('fs');
var file;
var buf = new Buffer(100000);
fs.open(
'info.txt', 'r',
function (handle) {
file = handle;
}
);
fs.read(
file, buf, 0, 100000, null,
function() {
console.log(buf.toString());
file.close(file, funtion () { /**/ });
}
);
它会抛出错误并退出。这是因为fs.open函数是异步执行的,它会在文件打开之前立刻返回,此时file变量的值仍然是undefined。
var fs = require('fs');
fs.open(
'info.txt', 'r',
function (handle) {
var buf = new Buffer(100000);
fs.read(
handle, buf, 0, 100000, null,
function() {
console.log(buf.toString());
file.close(file, funtion () { /**/ });
}
);
}
);
Node使用了事件队列。如果有挂起的事件等待响应,它就不会退出。
3.3 错误处理和异步函数
try {
setTimeout(function () { //在事件队列中添加了一个新事件后就返回。
throw new Error("uh oh!");
}, 2000);
} catch (e) {
console.log("I caught the error: " + e.message);
}
回调函数实际上是在一个全新的上下文和作用域中执行的。
因此,当在非阻塞IO中调用异步函数的时候,只有极小一部分会抛出错误;大部分情况下,编译器会告诉你出错了。
3.4 我是谁 --- 如何维护本体
var fs = require('fs');
function FileObject () {
this.filename = '';
this.file_exits = function ( callback ) {
var self = this; //通过闭包保留的
//console.log("About to open: " + this.filename );
console.log("About to open: " + self.filename );
fs.open(this.filename, 'r', function(err, handle) {
if (err) {
console.log("can't open: " + self.filename);
callback(err);
return ;
}
fs.close(handle, function() {});
callback(null, true);
});
};
};
var fo = new FileObject();
fo.filename = "file_that_does_not_exist";
fo.file_exits( function (err, results) {
if (err) {
console.log("Aw, bummer: " + JSON.stringify(err));
return ;
}
console.log("file exists!!!");
});
3.5 保持优雅 --- 学会放弃控制权
如果一个函数需要计算两个数组的交叉元素,会发生些什么呢:
并不意味着Node必须避免高强度计算的任务。如果只是偶尔执行这种任务,那么可以在使用,并且可以利用全局对象process中的nextTick方法。这种方法就好像在跟系统说“我放弃执行控制权,你可以在空闲时执行”。
3.6 同步函数调用
Node有一些核心API的同步版本,尤其是在操作文件的API中。
var fs = rquire('fs');
var hand = fs.openSync('info.txt', 'r');
var buf = new Buffer(100000);
var read = fs.readSync(handle, buf, 0, 10000, null);
console.log(buf.toString('utf8', 0, read));
fs.closeSync(handle);