异步的那些事儿,async
2015-04-18 本文已影响221人
忧郁的河蟹
回调,是每个nodejser必须面对的问题,社区也有很多解决方案,诸如asnyc,promise和ECMAScript 第六版的引入。异步的那些事儿,讲会围绕这三个方案来展开。
async
项目地址:https://github.com/caolan/async
async是最早在node.js社区流行的异步库,其简单的语法和相对绿色的封装,深受node.jser所爱,也是本人最常用的异步库。
相信语法这种东西,文档会比我描述得更详细,本文不会过多地介绍语法问题,侧重实现原理。下面将以几个本人认为比较经典的例子作为展开。
async核心代码
// assuming openFiles is an array of file names and saveFile is a function
// to save the modified contents of that file:
async.each(openFiles, saveFile, function(err){
// if any of the saves produced an error, err would equal that error
});
上面的函数,会遍历openFiles的数组,对文件进行读取,当全部文件内容都读取完毕后,执行最后的回调函数。
async.each = function (arr, iterator, callback) {
callback = callback || function () {};
if (!arr.length) {
return callback();
}
var completed = 0;
_each(arr, function (x) {
iterator(x, only_once(done) );
});
function done(err) {
if (err) {
callback(err);
callback = function () {};
}
else {
completed += 1;
if (completed >= arr.length) {
callback();
}
}
}
};
async.each(openFiles, saveFile, callback)
读取openFiles的数组长度,创建completed作为哨兵变量,每完成一件saveFile任务后,completed 自增1,当 completed 的大小等于 openFiles 的数组长度的时候,代表任务结束,回调函数。
实现非常简单,本人也实现了一个版本,可以参考一下。
var fs = require('fs');
async = {
map: function (arrs, iter, callback) {
var length = arrs.length;
var count = 0; //哨兵变量
var result = []; //结果缓存
var next = function (err, data) {
if (err) {
return callback(err); // 遇到错误马上跳出
}
result.push(data);
count += 1;
if (count === length) {
return callback(err, result);
}
};
arrs.forEach(function (arr) {
iter.call(null, arr, next);
})
}
};
async.map(['1.txt', '2.txt', '3.txt'], function (filename, next) {
fs.readFile(filename, 'utf-8', next);
}, function (err, result) {
console.log(result);
console.log('fin');
});
源码:
https://github.com/youyudehexie/nodejs-cookbook/blob/master/async/demo1.js