async.js助你处理js里面的并行和串行
作者:秋了秋 发表时间:2021年05月05日
在js中,尤其是nodeJs中,异步回调是家常便饭,随时会面临一大波的嵌套,或者是可以并行执行的代码因为不好处理何时结束而采用地狱嵌套一个个执行,嵌套到最后一个自然就全部都执行完了,这是最不需要动脑子的写法。还有一种是弄个变量,执行一个+1,执行一个+1,最终轮询这个变量,当这个值达到数据量最大的时候就断定全部执行完了。这比前者高级一点,至少比前者性能好,不需要等待时间,但是很别扭,每次写并行代码都要处理这种吗?显然不合适,而async.js就是封装了解决了我们所有困扰的工具。它包含了并行的处理,串行的处理,包括以上不涉及的错误处理、参数传递,主要封装了三大函数:
串行处理: 1.async.series([],function(err, callback){}); 2.async.waterfall([],function(err, callback){}); 并行处理: 3.async.parallel([],function(err, callback){});
第一个参数均为要执行的函数集合,为一个数组,并行处理series和waterfall 数组里面放的函数都是按前后执行,只有执行了前一个并且完成了才会执行下一个,第二个参数最终执行的回调函数,即数组里面所有的函数都执行完了就会跑到最终的回调函数执行最后的使命,如:
async.series([ function(callback) { setTimeout(function() { callback(null,1, 'a'); }, 1000) }, function(callback) { setTimeout(function() { callback(null,2); }, 1000) }, ],function(err, result){ console.log(result);//[[1,'a'], 2] });
解释下callback(null,1, 'a'); 第一个参数是错误(error),传null就是表示没有错误,才会执行下一个函数,1和‘a’是传递给最终回调函数的参数result, 以数组形式归集中间过程所有执行函数传过来的参数。
如果有一个函数有错误了则会中断执行下面的所有函数直接跳到最终回调。如:
async.series([ function(callback) { setTimeout(function() { callback('出错了,我不是null',1, 'a'); }, 1000) }, function(callback) { setTimeout(function() { callback(null,2); }, 1000) }, ],function(err, result) { console.log(err);//出错了,我不是null console.log(result);//[[1,'a']] });
则第二个函数将不会执行。
同理,waterfall也是如此,那为何搞了两个,传参形式不一样,比如说后一个执行的函数需要等待前一个函数执行完成后得到的某一个数据,那么就应该用waterfall,而最终回调函数的result也是中间所有函数最后执行的那个函数传过来的参数,如:
async.waterfall([ function(callback) { setTimeout(function(){ callback(null,1, 'a'); }, 1000) }, function(arg1, arg2, callback) { console.log(arg1, arg2);//1, 'a' setTimeout(function(){ callback(null,2); }, 1000); }, ],function(err, result) { console.log(result);//2 });
而并行处理parallel, 数组里面的函数是不分先后顺序,全部一起执行,所有函数都有返回结果后再执行最终回调函数,如:
async.parallel([ function(callback) { setTimeout(function() { callback(null,1, 'a'); }, 1000) }, function(callback) { setTimeout(function() { callback(null,2); }, 1000) }, ],function(err, result) { console.log(result);//[[1,'a'], 2] });
看起来跟串行函数series写法和参数是一模一样,区别是内部运行机制不一样,并行明显快得多,当函数与函数之间不需要依赖关系的时候,首选使用并行,因为它可以节省n倍时间。当函数之间有依赖的时候只能用waterfall或series,串行使用场景如:
某用户更新一篇文章,要先获取这篇文章的作者,判断作者是否是该用户,如果是才允许修改,不是的话禁止修改。
补充:parallel还有另外一种写法,第一个参数不是一个数组,而是对象,最终回调函数的result也是对象。如:
async.parallel({ one:function(callback) { setTimeout(function() { callback(null,1, 'a'); }, 1000) }, two:function(callback) { setTimeout(function() { callback(null,2); }, 1000) }, },function(err, result){ console.log(result);//{one:[1,'a'], two:2} });