js实现async.parallel功能

在有多个异步请求的情况下,如何将它们全部正确的返回请求是个问题。如果不适用async,一般有几种实现的情况。

1、对于result需要按照顺序请求的情况直接使用回调-回调-回调

直接使用这样的回调就能完成相应需求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var allResult = {}
asyncFunction("1",function(error,result){
if(error==null)
allResult["1"]=result
asyncFunction("2",function(error,result){
if(error==null)
allResult["2"]=result
asyncFunction("3",function(error,result){
if(error==null)
allResult["3"]=result
else
console.error(error)
})
else
console.error(error)
})
else
console.error(error)
})

这种请求方式虽然能很明确地描述出整个流程,能保证result按顺序输出,但是代码一层套一层,不利于阅读。

这种情况可以使用async.series进行控制,暂且不提

2、如果不要求按照顺序输出result,因此上面那种做法就显得非常浪费时间,因为每个请求都要等到前一个请求完成后才会进行下一个请求,它们的时间是相加的。因此可以同时进行所有的请求,将所有请求的result都拿到,不需要管它们哪个先输出哪个后输出。

在async中,可以这样实现:

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
async.parallel({
one:function(done){
asyncFunction('1',function(error,result){
if(!error)
done(null,result)
else
done(error,null)
})
},
two:function(done){
asyncFunction('2',function(error,result){
if(!error)
done(null,result)
else
done(error,null)
})
},
three:function(done){
asyncFunction('3',function(error,result){
if(!error)
done(null,result)
else
done(error,null)
})
}
},function(error,result){
if(!error)
callback(null,result)
else
callback(error,null)
});

以上代码的含义是,同时调用3个asyncFunction,当三个函数都成功取到result之后将result输出,如果其中有任何一个函数出现了错误(收到了error)则输出错误信息。通过这种方式可以节省请求时间且便于查看代码。

实现async.parallel

async.parallel参数由2部分,第一部分是由请求组成的对象,第二部分是全部完成时处理的函数

需要处理的第一点就是如何判断所有的asyncFunction都成功完成,且在那时候调用之后的函数.

可以采用for in 来获取第一部分参数的请求数量

1
2
3
4
5
6
7
async.parallel = function(actions,allDone){
var Result = {}
var n = 0
for(var action in actions){
if(actions.hasOwnProperty(action)) n++
}
}

这样就能获得请求总数,hasOwnproperty防止计数时遍历到其原型的属性

接着,就可以遍历请求,分别处理它们的回调了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
async.parallel = function(actions,allDone){
var Result = {}
var n = 0
for(var action in actions){
if(actions.hasOwnProperty(action)) n++
}
//得到了n
for(var action in actions){
var done = function(error,result){
if(error==null){
Result[action] = result
n--
if(n==0) allDone(null,Result)
}else{
allDone(error,Result)//如果asyncFunction发生错误,将错误返回
}
}
action(done)//将done作为参数放入每个请求中,用于处理result和error
}
}

通过这种方式,简单实现了async.parallel的功能。