nodejs中Async库使用

来源:互联网 发布:别人羡慕的生活知乎 编辑:程序博客网 时间:2024/05/16 17:46

“流程控制”本来是件比较简单的事,但是由于Nodejs的异步架构的实现方法,对于需要同步的业务逻辑,实现起来就比较麻烦。嵌套3-4层,代码就会变得的支离破碎了!

现在介绍一个库async ,链接是https://github.com/caolan/async

Async的内容分为三部分:

  • 流程控制:简化十种常见流程的处理
  • 集合处理:如何使用异步操作处理集合中的数据
  • 工具类:几个常用的工具类

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

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

step1(function(err, v1) {        step2(function(err, v2) {                step3(function(err, v3) {                        // do somethig with the err or values v1/v2/v3                }        }});

从中可以看到这嵌套还是比较多深的,如果再多几步,会更深。

在代码中忽略对了每一层err的处理,否则还都等加上 if(err) return callback(err),那就更麻烦了。

对于这种情况,使用async来处理,在每个step中执行一些操作,这时可写成:

var async = require('async');      async.series([          function(callback){              console.log('step1');          // do some stuff ...          callback(null, 'one');          },          function(callback){              console.log('step2');              // do some more stuff ...              callback(null, 'two');          }          ],           function(err, result) {              console.log(result);              // do somethig with the err or values v1/v2/v3          });

返回结果:

step1

step2

['one', 'two']

依次执行一个函数数组中的每个函数,每一个函数执行完成之后才能执行下一个函数。 
如果任何一个函数向它的回调函数中传了一个error,则后面的函数都不会被执行,并且将会立刻会将该error以及已经执行了的函数的结果,传给series中最后那个callback。 
当所有的函数执行完后(没有出错),则会把每个函数传给其回调函数的结果合并为一个数组,传给series最后的那个callback。 
还可以json的形式来提供tasks。每一个属性都会被当作函数来执行,并且结果也会以json形式传给series最后的那个callback。这种方式可读性更高一些。

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

并行执行多个函数,每个函数都是立即执行,不需要等待其它函数先执行。传给最终callback的数组中的数据按照tasks中声明的顺序,而不是执行完成的顺序。 
如果某个函数出错,则立刻将err和已经执行完的函数的结果值传给parallel最终的callback。其它未执行完的函数的值不会传到最终数据,但要占个位置。 
同时支持json形式的tasks,其最终callback的结果也为json形式。 
示例代码:

var async = require('async');async.parallel([    function(callback){        setTimeout(function(){            console.log('step1');            callback(null, 'one');        }, 200);    },    function(callback){        setTimeout(function(){            console.log('step2');            callback(null, 'two');        }, 100);    }],    // optional callback    function(err, results){        console.log(results);        // the results array will equal ['one','two'] even though        // the second function had a shorter timeout.});
返回结果:

step2

step1

['one', 'two']

waterfall(tasks, [callback]) (多个函数依次执行,且前一个的输出为后一个的输入)这个函数使用非常频繁

与seires相似,按顺序依次执行多个函数。不同之处,每一个函数产生的值,都将传给下一个函数。如果中途出错,后面的函数将不会被执行。错误信息以及之前产生的结果,将传给waterfall最终的callback。 
这个函数名为(瀑布),可以想像瀑布从上到下,中途冲过一层层突起的石头。

var async = require('async');async.waterfall([    function(callback){        callback(null, 'one', 'two');    },    function(arg1, arg2, callback){        console.log(arg1,arg2);        callback(null, 'three');    },    function(arg1, callback){        console.log(arg1);        // arg1 now equals 'three'        callback(null, 'done');    }], function (err, result) {    console.log(result);    // result now equals 'done'});

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

用来处理有依赖关系的多个任务的执行。比如某些任务之间彼此独立,可以并行执行;但某些任务依赖于其它某些任务,只能等那些任务完成后才能执行。 
虽然我们可以使用async.parallel和async.series结合起来实现该功能,但如果任务之间关系复杂,则代码会相当复杂,以后如果想添加一个新任务,也会很麻烦。这时使用async.auto,则会事半功倍。 
如果有任务中途出错,则会把该错误传给最终callback,所有任务(包括已经执行完的)产生的数据将被忽略。 
这里假设我要写一个程序,它要完成以下几件事: 
从某处取得数据 
在硬盘上建立一个新的目录 
将数据写入到目录下某文件 
发送邮件,将文件以附件形式发送给其它人。 
分析该任务,可以知道1与2可以并行执行,3需要等1和2完成,4要等3完成。

async.auto({        getData: function(callback) {                setTimeout(function() {                        console.log(’1 : got data’);                        callback();                },                300);        },        makeFolder: function(callback) {                setTimeout(function() {                        console.log(’1 : made folder’);                        callback();                },                200);        },        writeFile: ['getData', 'makeFolder',        function(callback) {                setTimeout(function() {                        console.log('1: wrote file');                        callback(null, 'myfile');                },                300);        }],        emailFiles: ['writeFile',        function(callback, results) {                log('1: emailed file: ', results.writeFile); // -> myfile                callback(null, results.writeFile);        }]},function(err, results) {        log(’1 : err: ‘, err); // -> null        log(’1 : results: ‘, results); // -> { makeFolder: undefined,        // getData: undefined,        // writeFile: ‘myfile’,        // emailFiles: ‘myfile’ }});



0 0
原创粉丝点击