【这是我参与更文挑战的第4天,活动详情查看: 更文挑战”】
【摘要】
Node.js的异步编程方式有效提高了应用性能,然而回调地狱却让人望而生畏,Promise让我们告别回调函数;在实践过程中,却发现Promise并不完美;技术进步是无止境的,后来有了Async/Await,让我们能够写出阻塞式的异步处理代码,然而对于一些流程控制方面还是很难写出优雅的代码。async.js的出现,能够写出简单清晰的异步流程控制代码。本文主要介绍项目中的常用方法。
项目官网:caolan.github.io/async/index…
简介
Async是一个流程控制工具包,提供了直接而强大的异步功能。基于Javascript为NodeJs设计,也可以直接在浏览器中使用。
在官方文档中,async.js的功能分为三个部分:流程控制、集合处理、工具。包括常用的 map, reduce, filter, forEach 等,异步流程控制模式包括:串行(series),并行(parallel),瀑布(waterfall)等。
常用方法介绍
parallel:多个任务并发执行
用于并行执行多个方法,所有传入的方法都是立即执行,方法之间没有数据传递。传递给最终callback的数组中的数据按照tasks中声明的顺序,而不是执行完成的顺序。
-
调用方式:parallel(tasks, [callback])
-
参数:
tasks:需要执行多个方法。tasks可以以数组形式传入,也可以以object对象形式传入。每个方法都要一个回调方法callback(err, result),回调方法需要提供一个err参数或是result参数。当发生错误时(即:err参数存在时),所有的方法停止执行,未执行完的方法将不会被传递至最终回调方法中。callback(err, results):可选的最终回调方法。出错时,tasks中抛出的错误将在此方法中捕获,错误被传入err参数。不出错时,tasks中回调结果将被写入results参数中,以数据或对象形式提供。
-
示例:
// 此段代码实现在传入uid,获取用户信息、用户文章列表、文章评论信息
Async.parallel({
account: callback => {
accountController.getByUid(keyword, callback);
},
articles: callback => {
articlesController.getByUid(keyword, callback);
},
comments: callback => {
commentsController.getByAid(keyword, callback);
}
},
(error, results) => {
console.log(results)
});
- 输出结果:
{
"account":{
"hash":"0x5eea3620415c6661912bb1c82aa7895f728e6258ea9d1b62f11acff7330f5cf1",
"timestamp"1546076450,
"name":"devpoint",
},
"articles":[],
"comments":null
}
series:多个任务依次执行
用于依次执行多个方法,一个方法执行完毕后才会进入下一方法,方法之间没有数据传递。
-
调用方式:
series(tasks, [callback]) -
参数:
tasks:需要执行多个方法。tasks可以以数组形式传入,也可以以object对象形式传入。每个方法都要一个回调方法callback(err, result),用于处理错误或进入下一方法。当发生错误时(即:err参数存在时),其后的方法会跳过,错误被传入最终回调方法中。
-
callback(err, results):可选的最终回调方法。出错时,tasks中抛出的错误将在此方法中捕获,错误被传入err参数。不出错时,tasks中回调结果将被写入results参数中,以数据或对象形式提供。 -
示例
//以数组形式传入需要执行的多个方法
Async.series(
[
callback => {
// 执行一些操作后,callback进入下一方法
callback(null, "one");
},
callback => {
// 执行一些操作后,callback进入可选的最终回调方法
callback(null, "two");
}
],
// 可选的最终回调
(err, results) => {
// 当tasks中的任一方法发生错误,即回调形式为callback('错误信息')时,错误将被传递给err参数,未发生错误err参数为空
// results中为数组中两个方法的结果数组:['one', 'two']
}
);
//以object对象形式传入需要执行的多个方法
async.series(
{
one: callback => {
// 执行一些操作后,callback进入下一方法
callback(null, 1);
},
two: callback => {
// 执行一些操作后,callback进入可选的最终回调方法
callback(null, 2);
}
},
(err, results) => {
// 当tasks中的任一方法发生错误,即回调形式为callback('错误信息')时,错误将被传递给err参数,未发生错误err参数为空
// results中为数组中两个方法的结果对象:{one: 1, two: 2}
}
);
waterfall:多个函数依次执行,且前一个的输出为后一个的输入
与series相似,按顺序依次执行多个函数。不同之处,每一个函数产生的值,都将传给下一个函数,如果中途出错,后面的函数将不会执行,错误信息以及之前产生的结果,都传给waterfall最终的callback。
这个函数的名字为waterfall(瀑布),可以想象瀑布从上到下,承上启下,有点类似于linux中的pipes。 注意该函数不支持object格式的tasks。
-
调用方式:
waterfall(tasks, [callback]) -
参数:
tasks:需要执行多个方法。tasks只能以数组形式传入。每个方法都要一个回调方法callback(err, result1, result2, ...),用于处理错误或进入下一方法。当发生错误时(即:err参数存在时),其后的方法会跳过,错误被传入最终回调方法中。无错误时回调参数result1, result2……将做为下一方法的输入参数callback(err, results):可选的最终回调方法。出错时,tasks中抛出的错误将在此方法中捕获,错误被传入err参数。不出错时,tasks中回调结果results为最后一个方法的回调结果。
-
示例:
Async.waterfall(
[
callback => {
callback(null, "one", "two");
},
(arg1, arg2, callback) => {
console.log("arg1=" + arg1 + ";arg2=" + arg2);
callback(null, "three");
},
(arg1, callback) => {
console.log("arg1=" + arg1);
callback(null, "done");
}
],
(err, result) => {
//执行的任务中方法回调err参数时,将被传递至本方法的err参数
//参数result为最后一个方法的回调结果'done'
console.log(result);
}
);
结果:
arg1=one;arg2=two
arg1=three
done
mapSeries:迭代执行,一个完了才执行下一个
迭代执行。将coll(是一个数组,不能是一个json对象)中的每一项依次拿给iterator去执行,执行结果传给最后的callback
-
调用方式:async.mapSeries(coll, iteratee, [callback])
-
参数:
coll:迭代的集合iteratee:迭代方法callback(err, results):可选的最终回调方法。
-
示例:
Async.mapSeries(
[1, 2, 3, 4],
(node, callback) => {
callback(null, node + 1);
},
(err, results) => {
console.log(results);
}
);
结果:[ 2, 3, 4, 5 ]