阅读 90

一个异步流程控制库:Async.js

【这是我参与更文挑战的第4天,活动详情查看: 更文挑战”】

【摘要】Node.js的异步编程方式有效提高了应用性能,然而回调地狱却让人望而生畏,Promise让我们告别回调函数;在实践过程中,却发现Promise并不完美;技术进步是无止境的,后来有了Async/Await,让我们能够写出阻塞式的异步处理代码,然而对于一些流程控制方面还是很难写出优雅的代码。async.js的出现,能够写出简单清晰的异步流程控制代码。本文主要介绍项目中的常用方法。

项目官网:caolan.github.io/async/index…

image.png

简介

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 ]

项目地址:github.com/caolan/asyn…

文章分类
前端