magic-task
magic-task可以让JavaScript异步编程更加简单、优雅、安全,它将异步过程抽象成一个个任务,并且使用Promise确保安全可靠,可以做统一的错误处理,还提供了常用的流程控制,使得代码更易于组织。
执行环境
- node.js - v0.12.x
- node.js - v0.11.x 开启Promise功能
- io.js
开始
以下是执行一个典型的异步任务的例子,这个任务包含了调用异步函数获取数据和数据处理过程。
var magicTask = ;var fs = ;var { fs; task;};magicTask;
当然,仅仅是执行这样简单的文件操作处理并不需要magic-task,直接调用异步函数将处理过程写在回调函数里即可,或是直接使用Promise。在流程稍微复杂的情况下,magic-task才慢慢显示出威力。例如需要多次数据库操作:
var magicTask = ;var mongoose = ;var User = mongoose;var Comment = mongoose; var { taskpromise = User;};var { if data task; else var user = ; user; };var { var comment = poster: data ; comment;};// 依次执行上面的任务magicTask;
定义任务
magic-task的一个任务是一个如下形式的函数:
// 参数task是一个任务控制器,提供done、fail、promise、async方法,这在下面的内容中会具体介绍// 参数data是任务接受的数据,取决于具体任务而定,例如waterfall任务中,每个任务的data是上一个任务的返回值,而each、map任务中data则是数组元素// 任务执行完成后可以返回结果,用于某些执行方法的数据传递或是流程控制 { // 在这里定义任务}
一共有3种任务类型:
便捷的异步任务
定义方式如下:
{ // 调用一个异步函数,例如fs.readfile // 如果异步函数的回调函数形式如function([err, ][arg1[, arg2[, arg3...]]]) {}, // 即第一个参数为返回的错误,后面的为返回的数据, // 那么可以调用task.async方法,简单地处理数据并处理错误 ; // 定义成功后的数据处理函数(可以不写,默认返回data) task { // 上面的异步函数asyncFunction执行成功后,可在这里写处理代码 // data为获取到的数据 // 如果上述的asyncFunction执行后的回调函数提供多个数据,则会合并到一个数组中,例如 // asyncFunction(args, function(err, arg1, arg2) {}) // 此时data为[arg1, arg2] return res; // 返回任务结果 };}
magic-task还提供另一个便捷的方法task.send(data)
:
{ // 这个方法默认asyncFunction的回调函数第一个参数为err,忽略其它参数 // 如果没有错误,那么会将字符串'custom data'作为任务执行成功后的结果 ;}
Promise任务
定义方法与上述的异步任务有些相似:
{ taskpromise = { if something ; else ; }; // 定义成功后的数据处理函数(可以不写,默认返回data) task { // data 等于 prData return res; //返回任务结果 };}
自定义任务
在一些特殊的异步或是同步过程时,可以使用更灵活的任务定义方式:
{ ;}
注意
不要在重新定义task.done后再调用task.done(res)来表示任务成功并返回结果,例如:
{ task {}; task; // 注意!!!这是错误的方法,任务并不会成功!!!}
执行任务
定义好任务后,就可以使用magic-task的方法来执行了,magic-task可以顺序、并发、循环执行任务,还可以执行顺序或并发的数组遍历任务。magic-task提供以下的方法来执行任务:
这些方法都会返回一个Promise,这样可以组合使用,应对更复杂的异步流程。 如果没有特别说明,成功执行后获得的数据为最后一个任务返回的数据。
run(task, data)
执行单个任务,data为传递给这个任务的数据。
示例
var { task;};magicTask;
waterfall(taskList)
顺序执行一系列任务,每个任务的返回结果为下一个任务function(task, data) {}
中的参数data
。如果taskList中的某个任务的返回结果为magicTask.end,则waterfall直接成功结束,不再执行其后面的任务。
示例
var { task; };var { console; // taskData_1 task;};var { console; // taskData_2 task;};magicTask; var { task; };var { // 不会执行该任务了 task;};magicTask;
parallel(taskList)
并发执行一系列任务,所有任务都执行成功后才算成功,执行成功后的结果为一个数组。
示例
magicTask;
each(array, iterTask)
执行遍历数组,迭代任务iterTask中function(task, data){}
的data为数组元素,迭代任务会顺序执行,一个任务完成后才会进行下一个任务。
示例
var array = 1 2 3;var { console; task;};magicTask;// 会依次输出1, 2, 3
map(array, iterTask)
执行遍历数组,迭代任务iterTask中function(task, data){}
的data为数组元素,迭代任务会并发执行,所有任务都成功后才算执行成功,执行的结果为一个数组,类似于parallel方法。
示例
var array = 1 2 3;var { ;};magicTask;
whilst(condTask, loopTask)
执行循环任务,第一个任务为条件判断,第二个任务为循环体,相当于while(cond) {body}
示例
var i = 0;var { ;};var { console; // 依次输出undefined, 1, 2 i++; task;};magicTask;
doWhilst(loopTask, condTask)
执行循环任务,第一个任务为循环体,第二个任务为条件判断,相当于do {body} while(cond);
,类似于whilst
方法。