Async 异步转同步详细流程解释

 

安装javascript

npm install async --savejava

地址node

https://github.com/caolan/asynclinux

Async的内容主要分为三部分

  1. 流程控制: 简化九种常见的流程的处理
  2. 集合处理:如何使用异步操做处理集中的数据
  3. 工具类:几个经常使用的工具类

本文主要介绍流程控制部分,后续内容持续更新,因为node.js是异步编程模型,有许多在同步编程中很容易作到的事情,如今就会变的很麻烦,而且存在不少的callback。可是,Async的流程控制给咱们coder带来了许多便利。


1.series(task, [callback])(多个函数依次执行,之间没有数据交换)

有多个异步函数须要依次调用,一个完成以后才能执行下一个。各函数之间没有数据交换,仅仅须要保证其顺序执行。这时可使用series。git

js代码github

step1(function (err, v1) { step2(function(err, v2){ step3(function(err,v3){ //code with the value [v1|v2|v3] or err }); }); });

从上面的代码中能够看到,这些嵌套仍是比较深的,若是操做更加复杂,那么会让代码的可读性下降。此外,在代码中忽略了对每一层err的处理,不然还要加上if(err) return callback(err); 那就更麻烦了。npm

对于这种状况,咱们可使用async来处理编程

var async = require('async'); async.series([ function(callback){ step1(function(err, v1){ //code with v1 callback(err, v1); }); }, function(callback){step2(……)}, function(callback){step3(……)} ],function(err, values){ //code with the value [v1|v2|v3] or the err }); 

上述async的详细解释为json

  1. 依次执行一个函数数组中的每一个函数,每个函数执行完成以后才能执行下一个函数。
  2. 若是任何一个函数向它的回调函数中传了一个error,则后面的函数都不会被执行,而且将会马上将该error以及已经执行了的函数的结果,传给series中最后的那个callback。
  3. 将全部的函数执行完后(没有出错),则会把每一个函数传给其回调函数的结果合并为一个数组,传给series最后的那个callback。
  4. 还能够以json的形式提供tasks。每个属性都会被看成函数来执行,而且结果也会以json形式传给series中最后的那个callback。这种方式可读性更高

注: 多个series调用之间是不分前后的,由于series自己也是异步调用。数组

2.parallel(tasks,[callback])(多个函数并行执行)

并行执行多个函数,每一个函数都是马上执行,不须要等待其余函数先执行。传给最终callback的数组中的数据按照tasks声明的顺序,而不是执行完成的顺序

若是某个函数出错,则马上将err和已经执行完的函数的结果值传给parallel最终的callback。其它为执行完的函数的值不会传到最终数据,但要占个位置。

同时支持json形式的tasks,其最终callback的结果也为json形式。

正常执行的代码以下:

async.parallel([ function(callback){t.fire('f400', callback, 400)}, function(callback){t.fire('f200', callback, 200)}, function(callback){t.fire('f300', callback, 300)} ],function(err, results){ log(err); //->undefined log(results); //->['f400', 'f200', 'f300'] });

中途出错的代码以下:

async.parallel([ function(callback){t.fire('f400', callback, 400)}, function(callback){t.fire('f200', callback, 200)}, function(callback){t.err('e300', callback, 300)} ], function(err, results){ log(err); //->e300 log(results); //->[, 'f200', undefined] }); 

3.waterfall(tasks, [callback])(多个函数依次执行,且前一个的输出为后一个的输入)

与series类似,按顺序依次执行多个函数。不一样之处,每个函数产生的值,都将传给下一个函数,若是中途出错,后面的函数将不会执行,错误信息以及以前产生的结果,都传给waterfall最终的callback。

这个函数的名字为waterfall(瀑布),能够想象瀑布从上到下,承上启下,有点相似于linux中的pipes。 注意该函数不支持json格式的tasks。

async.waterfall([ function(callback){log('start'), callback(null, 3)}, function(n, callback){log(n), t.inc(n, cb);/*inc为相似于i++的函数*/}, function(n, callback){log(n), t.fire(n*n, cb);} ], function(err, results){ log(err); log(results); }); /** output start 3 4 err: null results: 16 */

4.auto(tasks, [callback])(多个函数有依赖关系, 有的并行执行,有的一次执行)

auto能够弥补parallel和series中的不足

例如我要完成下面的事情

  1. 从某处取得数据
  2. 在硬盘上创建一个新的目录
  3. 将数据写入到目录下某文件
  4. 发送邮件
async.auto({ getData: function(callback){ setTimeout(function(){ console.log('got data'); callback(null, 'mydata'); }, 300); }, makeFolder: function(callback){ setTimeout(function() { console.log('made folder'); callback(null, 'myfolder'); }, 200); }, writeFile:['getData', 'makeFolder', function(callback){ setTimeout(function(){ console.log('write file'); callback(null, 'myfile'); }, 300); }], emailFiles: ['writeFile', function(callback, results){ log('send email'); callback(null, results.writeFile); }] },function(err, results){ log(err); //->null log(results); //made folder //got data //write file //send email /* results{ makeFolder: 'myfolder', getData: 'mydata', writeFile: 'myfile', emailFiles: 'myfile' } */ });

5.whilst(test, fn, callback)(该函数的功能比较简单,条件变量一般定义在外面,可供每一个函数访问。在循环中,异步调用时产生的值实际上被丢弃了,由于最后的callback只能传入错误信息,另外,第二个函数fn须要接受一个函数的cb, 这个cb最终必需被执行,用于表示出错或正常结束)

var count = 0; async.whilst( //test function(){return count < 3;}, function(cb){ log(count); count++; setTimeout(cb, 1000); }, function(err){ //3s have passed log(err); } ); /* 0 1 2 null */

6.until(test, fn, callback)(与whilst类似,但判断条件相反)

var count_until = 0; async.until( //test function(){ return count_until > 3;}, function(cb){ log(count_until); count_until++; setTimeout(cb, 1000); }, function(err){ //4s have passed log(err); } ); /* 0 1 2 3 null */

7.queue(可设定worker数量的队列)

queue至关于一个增强版的parallel, 主要限制了worker数量,再也不一次性所有执行。当worker数量不够用时,新加入的任务将会排队等候,直到有新的worker可用。

该函数有多个点可供回调,如worker用完时、无等候任务时、所有执行完时等。

//定义一个queue, 设worker数量为2 var q = async.queue(function(task, callback){ log('worker is processing task: ' + task.name); task.run(callback); }, 2); //监听:若是某次push操做后, 任务数将达到或超过worker数量时, 将调用该函数 q.saturated = function(){ log('all workers to be used'); } //监听:当最后一个任务交给worker时,将调用该函数 q.empty = function(){ log('no more tasks waiting'); } //监听:当全部任务都执行完之后,将调用该函数 q.drain = function(){ log('all tasks have been processed'); } //独立加入两个任务 q.push({name : 't1', run: function(cb){ log('t1 is running, waiting tasks:' + q.length()); t.fire('t2', cb, 400); //400ms后执行 }}, function(err){ log('t1 executed'); }); log('pushed t1, waiting tasks:' + q.length()); q.push({name: 't2', run: function(cb){ log('t2 is running, waiting tasks:' + q.length()); t.fire('t2', cb, 200); //200ms后执行 }}, function(err){ log('t2 executed'); }); log('pushed t2, waiting tasks:' + q.length()); /** pushed t1, waiting tasks:1 all workers to be used pushed t2, waiting tasks:2 worker is processing task : t1 t1 is running, waiting tasks: 1 no more tasks waiting worker is processing task : t2 t2 is running, waiting tasks: 0 t2 executed t1 executed all tasks have been processed */

8.iterator(tasks)(将几个函数包装为iterator)

将一组函数包装成为一个iterator, 可经过next()获得如下一个函数为起点的新的iterator。该函数一般由async在内部使用,但若是须要时,也可在咱们的代码中使用它。

var iter = async.iterator([ function(){console.log('111');}, function(){console.log('222');}, function(){console.log('333');} ]); var it1 = iter(); it1(); 

其中还包括了next()方法。

9.nextTick(callback)(在nodejs与浏览器两边行为一致)

nextTick的做用和nodejs的nextTick同样,都是把某个函数调用放在队列的尾部,但在浏览器端,只能使用setTimeout(callback, 0),但这个方法有时候会让其它高优先级的任务插到前面去。

因此提供了这个nextTick,让一样的代码在服务器端和浏览器端表现一致。

var calls = []; async.nextTick(function(){ calls.push('two'); }); calls.push('one'); async.nextTick(function(){ console.log(calls); //-> ['one', 'two'] })

上述内容为学习笔记,大部份内容摘抄自alsotang的github中的async_demo,网址

相关文章
相关标签/搜索