Node.js中Async详解:流程控制

安装

npm install async --save

地址

https://github.com/caolan/async

Async的内容主要分为三部分

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

本文主要介绍流程控制部分,后续内容持续更新,由于node.js是异步编程模型,有许多在同步编程中很容易做到的事情,现在就会变的很麻烦,并且存在很多的callback。但是,Async的流程控制给我们coder带来了许多便利。


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

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

纯js代码

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);
那就更麻烦了。

对于这种情况,我们可以使用async来处理

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

上述async的详细解释为

  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); //->undefinedlog(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); //->e300log(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);
});/**outputstart34err: nullresults: 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); //->nulllog(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(//testfunction(){return count < 3;},function(cb){log(count);count++;setTimeout(cb, 1000);},function(err){//3s have passedlog(err);}
);
/*012null
*/

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

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

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:1all workers to be usedpushed t2, waiting tasks:2worker is processing task : t1t1 is running, waiting tasks: 1no more tasks waitingworker is processing task : t2t2 is running, waiting tasks: 0t2 executedt1 executedall 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']
})

转自:http://www.cnblogs.com/chunzhulovefeiyue/p/7229735.html

Node.js中Async详解相关推荐

  1. 《Node.js开发实战详解》学习笔记

    <Node.js开发实战详解>学习笔记 --持续更新中 一.NodeJS设计模式 1 . 单例模式 顾名思义,单例就是保证一个类只有一个实例,实现的方法是,先判断实例是否存在,如果存在则直 ...

  2. Node.js 应用开发详解04 3 大主流系统框架:由浅入深分析 Express、Koa 和 Egg.js

    上一讲我们没有应用任何框架实现了一个简单后台服务,以及一个简单版本的 MSVC 框架.本讲将介绍一些目前主流框架的设计思想,同时介绍其核心代码部分的实现,为后续使用框架优化我们上一讲实现的 MSVC ...

  3. Node.js 从门详解 (二)

    目录 1. 模块化的基本概念 1.1 什么是模块化 1.2 模块化规范 2. Node.js 中模块化 2.1 Node.js 中模块的分类 2.2 加载模块 2.3 Node.js中的模块作用域 2 ...

  4. Node.js websocket/ws 详解

    前言 众所周知,HTTP协议是一种无状态.无连接.单向的应用层协议,只能由客户端发起请求,服务端响应请求. 这就显示了一个明显的弊端:服务端无法主动向客户端发起消息,一旦客户端需要知道服务端的频繁状态 ...

  5. Node.js和npm详解(直接上手演示)

    我们先直接操作一下,让你们看效果,刚开始文字说的再多也比不上看一遍效果! 我们用java语言来比较一下 首先java语言是如何在桌面进行编译的呢? 第一步:编写java文件 第二步:在cmd命令框中输 ...

  6. Node.js HTTP 使用详解

    对于初学者有没有发觉在查看Node.js官方API的时候非常简单,只有几个洋文描述两下子,没了,我第一次一口气看完所以API后,对于第一个示例都有些懵,特别是参数里的request和response, ...

  7. 【Node.js】关于Node.js接口的详解和案例--restful风格接口。案例:添加商品接口,添加员工接口,删除员工接口

    1.首先我们需要知道,接口是什么? 接口是后端为前端提供的数据--动态资源:Node.js通过每一个路由就可以实现接口 2.RESTful接口:是一种接口的架构风格 1.请求的URL(资源) 在资源前 ...

  8. js中 json详解

    var aa ={name:"zoumm",age:23};var bb = JSON.stringify(aa);console.log(bb); //打印出{"nam ...

  9. 阿里云ECS服务器部署Node.js项目全过程详解

    本文详细介绍如何部署NodeJS项目到阿里云ECS上,以及本人在部署过程中所遇到的问题.坑点和解决办法,可以说是全网最全最详细的教程了.同时讲解了如何申请阿里云免费SSL证书,以及一台ECS服务器配置 ...

最新文章

  1. python之__name__
  2. 数据流图怎么画_概率图模型怎么画?5个步骤完成专业模型图
  3. 线性代数拾遗(四):线性方程组的应用
  4. 用xargs处理带空格文件名
  5. 中科院院士张钹:大数据驱动的人工智能有大量毛病,且是根本性的
  6. 解决 Failed to connect to github.com port 443:connection timed out
  7. 0=iiLen 在C++中
  8. 《Cracking the Coding Interview》——第8章:面向对象设计——题目9
  9. ES9218PC SABRE HiFi 移动 DAC 便携式耳放
  10. cdr多页面排版_CDR文字排版实战图文教程,CorelDRAW文字排版有哪些技巧?
  11. 前端面试题之 对Promise的理解
  12. 【MySQL】MySQL的锁与事务隔离级别详解
  13. SCSS 和 Sass 有什么区别?
  14. java 金额的大小写转换类
  15. 关于微信小程序第三方客服接入调查
  16. 教你在python中用不同的方式画不同颜色的画布
  17. 魔兽地图服务器存档修改本地存档,【Jass】Preload存档系统,本地写入文件并读取...
  18. python学习笔记3(字符串)
  19. 网络攻防实验之缓冲区溢出攻击
  20. HOUDINI TIP | USING HOU MODULE IN VISUAL STUDIO CODE_手动在vscode里设置houdiniPython模块

热门文章

  1. PHP中的MD5加密
  2. strassen矩阵乘法c语言代码,计算机算法:Strassen矩阵乘法
  3. sql2005服务和连接的外围应用配置器打不开解决方法
  4. nginx代理openfire
  5. IntelliJ IDEA快捷键大全 + 动图演示,建议收藏!
  6. MySql 获取年月日 时分秒、年月日、年月、年、月
  7. MAP使用containsKey和containsValue方法,验证键值对是否存在此KEY或VAL值。
  8. Tag标签的含义介绍以及怎么去做优化
  9. 币圈科学家系列:pancake闪电贷
  10. Surface 和 SurfaceHolder