使用 Async.js 简化你的 JavaScript 代码
Async.js 是一个功能强大的库,主要是基于 Node.js 开发,他本身也是 JavaScript 代码,在 Web 浏览器中也可以单独使用,它可以简化 Node.js 异步操作的书写,使代码更容易被读懂。
安装Async.js
我们可以使用Node.js的包管理器npm直接安装它,在shell中输入:
npm install async
或者更改package.json文件,自定义安装的细节:
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
......
"async":"~0.9.0"
}
}
然后运行 npm install
安装完成后,在需要使用它的文件中加入:
var async = require('async');
Series
使用series
可以简化流程运行的异步函数,现在构想一个这样的场景,我需要执行一组动作,喝水 -> 吃饭 -> 打开电脑,通常的代码编写应该这样:
function normalFunc() {
console.log("Normal function Run");
drinkWater(function (error,data) {
if(error) {
console.log("error: ",error,"msg: ",data);
} else {
console.log("drink water finish, I will eat food");
eatFood(function(error,data) {
if(error) {
console.log("error: ",error,"msg: ",data);
} else {
console.log("eat food finish, I will open mac");
openMac(function(error,data) {
if(error) {
console.log("error: ",error,"msg: ",data);
} else {
//do something after open mac
console.log("Mac is open, all action done");
}
});
}
});
}
});
}
当异步调用超过两次嵌套,代码会变得不直观。使用async.series可以优化:
function seriesFunc() {
async.series([
function(callback) {
console.log("Series function Run");
drinkWater(function(error,data) {
callback(error,data);
});
},
function(callback) {
console.log("drink water finish, I will eat food");
eatFood(function(error,data) {
callback(error,data);
});
},
function(callback) {
console.log("eat food finish, I will open mac");
openMac(function(error,data) {
callback(error,data);
});
}],
function(error,result) {
if(error) {
console.log("error: ",error,"msg: ",result);
}
else {
console.log("Mac is open, all action done");
}
}
);
}
为了测试这个例子,我编写三个函数:
function drinkWater(callback) {
callback(null,null);
}
function eatFood(callback) {
callback(null,null);
}
function openMac(callback) {
callback(null,null);
}
接下来,我们测试这些函数,在console中的显示是下面的代码:
Normal function Run
drink water finish, I will eat food
eat food finish, I will open mac
Mac is open, all action done
Series function Run
drink water finish, I will eat food
eat food finish, I will open mac
Mac is open, all action done
这样看,我们达到了相同的效果。我们再测试出错的情况,将openMac函数更改成下面的代码:
function openMac(callback) {
callback(1,"I can't find my mac");
}
再测试这两个函数:
Normal function Run
drink water finish, I will eat food
eat food finish, I will open mac
error: 1 msg: I can't find my mac
Series function Run
drink water finish, I will eat food
eat food finish, I will open mac
error: 1 msg: [ null, null, 'I can\'t find my mac' ]
我们能发现 series 的 result是一个数组。series中的callback被执行后,无论动作的结果是成功还是失败,都会在result中添加一个数据。另一方面,我们也可以通过result中元素的数量,判断 series 执行了几个函数。
Waterfall
另一个有用函数是 waterfall 。它和 series 一样,可以简化流程运行的异步函数。不同点是它可以在流程执行的过程中传递参数。
例如,我需要在异步函数中返回一些饮品或食物的信息,我需要更改
function drinkWater(callback) {
callback(null,"Cola");
}
function eatFood(callback) {
callback(null,"Hamburger");
}
function openMac(callback) {
callback(null,"Chrome");
}
然后添加:
function waterFunc() {
async.waterfall([
function(callback) {
console.log("Water Fall Run");
drinkWater(function(error,data) {
callback(error,data);
});
},
function(data,callback) {
console.log("drink ",data," finish, I will eat food");
eatFood(function(error,data) {
callback(error,data);
});
},
function(data,callback) {
console.log("eat ",data," finish, I will open mac");
openMac(function(error,data) {
callback(error,data);
});
}],
function(error,result) {
if(error) {
console.log("error: ",error,"msg: ",result);
}else {
console.log("Mac ",result," is open, all action done");
}
}
);
}
每一次运行函数的回调结果都会传给下一个动作,最后的result与series不同,是最后一次执行动作callback中传递的值。运行测试结果为:
Water Fall Run
drink Cola finish, I will eat food
eat Hamburger finish, I will open mac
Mac Chrome is open, all action done
然后再来测试出错的情况,更改:
function eatFood(callback) {
callback(1,"not enough money");
}
再运行的结果是:
Water Fall Run
drink Cola finish, I will eat food
error: 1 msg: not enough money
总结
使用Node.js中的 Async 可以将复杂的逻辑表现的更直观。但如果逻辑只有一次回调,就不建议使用Async了,我认为这会无意义的增加一些运行的成本。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论