Skip to content

Instantly share code, notes, and snippets.

@leizongmin
Created May 17, 2012 09:12
Show Gist options
  • Save leizongmin/2717618 to your computer and use it in GitHub Desktop.
Save leizongmin/2717618 to your computer and use it in GitHub Desktop.
JavaScript简单异步执行
/**
* 使用方法:
* step(function (data, next) {
* // step 1, do somethings...
* next(null, data);
* }, function (data, next) {
* // step 2, do somethings...
* next(null, data);
* }, function (err, data) {
* // callback
* });
* 说明:
* 前N-1个参数为要顺序执行的函数,接收两个参数: data和next,参数data可用于传递结果给下个执行的函数,参数next用于执行下一个函数
* 最后一个参数为所有步骤执行完毕(或中途出错)后的回调函数,接收两个参数:err和data,如果中途出错,则err不等于null
*/
function step () {
var fn = [];
for (var i = 0, len = arguments.length - 1; i < len; i++) {
fn.push(arguments[i]);
}
var callback = arguments[i];
var i = -1;
var next = function (err, data) {
if (err) {
return callback(err, data);
}
i++;
if (typeof fn[i] === 'function') {
try {
return fn[i](data, next);
}
catch (err) {
return callback(err, data);
}
}
else {
return callback(null, data);
}
};
next(null, {});
};
// 例1:
step(
function (data, next) {
data.num1 = Math.random();
setTimeout(function () {
next(null, data);
}, 50);
},
function (data, next) {
data.num2 = Math.random();
setTimeout(function () {
next(null, data);
}, 20);
},
function (data, next) {
data.num3 = Math.random();
setTimeout(function () {
next(null, data);
}, 100);
},
function (err, data) {
console.log(err, data);
}
);
// 例2(中途出错):
step(
function (data, next) {
data.num1 = Math.random();
next(null, data);
},
function (data, next) {
data.num2 = Math.random();
next(null, abcd);
},
function (data, next) {
data.num3 = Math.random();
next(null, data);
},
function (err, data) {
console.log(err, data);
}
);
// 例3(Node.js异步方式读取目录下文件的属性):
var fs = require('fs');
fs.readdir('.', function (err, files) {
if (err)
throw err;
var readFileStat = function (file) {
return function (data, next) {
fs.stat(file, function (err, stats) {
if (err)
return next(err);
data[file] = stats;
next(null, data);
});
};
};
var fn = [];
for (var i = 0, len = files.length; i < len; i++)
fn.push(readFileStat(files[i]));
fn.push(function (err, data) {
if (err)
throw err;
console.log(data);
});
step.apply(null, fn);
});
// 例4(Node.js异步方式遍历目录):
var fs = require('fs');
var path = require('path');
function expand (dir, callback) {
try {
fs.readdir(dir, function (err, files) {
if (err)
return callback(err);
var fn = [];
for (var i = 0, len = files.length; i < len; i++)
fn.push(_expandChild(path.join(dir, files[i])));
fn.push(function (err, data) {
if (err)
return callback(err);
callback(null, data.files || []);
});
step.apply(null, fn);
});
}
catch (err) {
return callback(err);
}
}
function _expandChild (dir) {
return function (data, next) {
if (!Array.isArray(data.files))
data.files = [];
data.files.push(dir);
fs.stat(dir, function (err, stats) {
if (stats.isDirectory()) {
console.log('[dir] ' + dir);
expand(dir, function (err, files) {
if (err)
return next(err);
data.files = files.concat(data.files);
next(null, data);
});
}
else {
console.log('[File] ' + dir);
next(null, data);
}
});
};
}
expand(path.resolve('../'), function (err, files) {
if (err)
console.log(err.stack);
console.log(files);
});
setInterval(function () {
console.log(' Time: ' + new Date());
}, 50);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment