async Node.js
async 是Javascript的扩展库。它可以简化Node.js异步操作的书写,使代码更容易被读懂,而不是面对多层的括号发疯。
我们可以使用Node.js的包管理器npm直接安装它,在shell中输入:
1 2 |
npm install async |
或者 更改package.json:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "name": "application-name", "version": "0.0.1", "private": true, "scripts": { "start": "node ./bin/www" }, "dependencies": { ...... "async":"~0.9.0" } } |
然后运行 npm install
. 安装完成后,在需要使用它的文件中加入:
1 2 |
var async = require(‘async‘); |
series
使用series
可以简化流程运行的异步函数。
现在构想一个这样的场景:
我需要执行一组动作,喝水 -> 吃饭 -> 打开电脑
通常的代码编写应该这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
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可以优化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
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"); } } ); } |
为了测试这个例子,我编写三个函数:
1 2 3 4 5 6 7 8 9 10 |
function drinkWater(callback) { callback(null,null); } function eatFood(callback) { callback(null,null); } function openMac(callback) { callback(null,null); } |
接下来,我们测试这些函数,在console中的显示是下面的代码:
1 2 3 4 5 6 7 8 9 10 |
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函数更改成下面的代码:
1 2 3 4 |
function openMac(callback) { callback(1,"I can‘t find my mac"); } |
再测试这两个函数:
1 2 3 4 5 6 7 8 9 10 |
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 一样,可以简化流程运行的异步函数。不同点是它可以在流程执行的过程中传递参数。
例如,我需要在异步函数中返回一些饮品或食物的信息,我需要更改
1 2 3 4 5 6 7 8 9 10 |
function drinkWater(callback) { callback(null,"Cola"); } function eatFood(callback) { callback(null,"Hamburger"); } function openMac(callback) { callback(null,"Chrome"); } |
然后添加:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
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中传递的值。运行测试结果为:
1 2 3 4 5 |
Water Fall Run drink Cola finish, I will eat food eat Hamburger finish, I will open mac Mac Chrome is open, all action done |
然后再来测试出错的情况,更改:
1 2 3 4 |
function eatFood(callback) { callback(1,"not enough money"); } |
再运行的结果是:
1 2 3 4 |
Water Fall Run drink Cola finish, I will eat food error: 1 msg: not enough money |
总结
使用 async node.js 可以将复杂的逻辑表现的更直观。但如果逻辑只有一次回调,就不建议使用async了,我认为这会无意义的增加一些运行的成本。
本文出自: [ 松阳的博客 ] / [ blog.csdn.net/fansongy ] 禁止用于商业用途 转载请注明出处
原文链接: http://www.songyang.net/async-node-js/