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了,我认为这会无意义的增加一些运行的成本。
本篇博客出自阿修罗道,转载请注明出处,禁止用于商业用途:http://blog.csdn.net/fansongy/article/details/42156109