javascript的异步、同步、回调和时间循环等概念就不解释了,google一下,一大堆精品文章。这里简单记录一下javascript的异步编程常用套路。
就以nodejs的fs模块读取文件为例吧。
var fs = require("fs");
var fileContent = fs.readFileSync('test.js','utf8');
console.log(fileContent);
console.log("something else");
var fs = require("fs");
fs.readFile('async.js','utf8',function(err,data){
if(!err) {
console.log(data);
}
});
console.log("something else");
这个代码就是javascript中最原始的异步编程。用这种原始的方法会带来一些弊端,比如回调地狱。
为了让开发者能够优雅地写javascript代码,能工巧匠们发明了一下几种方法。
var fs = require("fs");
fs.readFile('async.js','utf8',fileContent);
function fileContent(err,data) {
if(!err) {
console.log(data);
}
}
这么干也有一个弊端,就是动不动就要为回掉函数命名,很是让人头疼,你懂的。
用generator“异步转同步”的典型当属tj大神的co库。看下面代码。
var fs = require('fs');
var co = require('co');
co(function* () {
var file1 = yield readFile('demo.js');
console.log(file1);
console.log("I am after file read even though its Async");
});
function readFile(filename) {
return function(callback) {
fs.readFile(filename, 'utf8', callback);
};
}
co用起来令人费解。
像q
, bluebird
这些库使用promise“碾平”了javascript回调函数带来的“金字塔”。
var Promise = require('bluebird');
// Converts all function of 'fs' into promises.
var fs = Promise.promisifyAll(require('fs'));
fs.readFileAsync('file.js','utf8')
.then(function(data) {
console.log(data);
})
.catch(function(err) {
console.log(err);
});
promise很有前途。
nodejs原生模块EventEmitter可以让开发者很方便地进行基于事件编程。
var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter();
var fs = require('fs');
// Event to read file - generic function.
emitter.on('start_read',function(file_name) {
console.log("Started Reading file....\n\n");
fs.readFile(file_name, 'utf8', function (err,data) {
if (err) {
console.log("Error happens.");
} else {
console.log("File data", data);
}
});
});
// Let's read some file.
emitter.emit('start_read','env.json');
emitter.emit('start_read','envConfig.js');
事件驱动,大材小用了。
Async.js解决异步问题“爽的”没得说。看看github上到star数就知道它不是泛泛之辈。