首页 > 代码库 > 使用 async Node.js 简化Javascript代码

使用 async Node.js 简化Javascript代码

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/


使用 async Node.js 简化Javascript代码