在NodeJS中使用流程控制工具Async
本文介绍一款流程控制工具async,在编写接口或者编写测试用例的过程中总是会用到它。
由于nodejs是异步编程模型,有一些在同步编程中很容易做到的事情,现在却变得很麻烦。Async的流程控制就是为了简化这些操作。
在node.js的开发和学习过程中,开始我们的目的只有一个就是实现功能,并不注重代码质量和可读性,也没有这个意识。像我之前在接口的实现过程中滥用中间件,以为结果出来了,把它response.send(result)出去就万事大吉了。
后来参考别人的代码,真心感到惭愧,然后才一步步学会注重代码的可读性。对比一下,之前的代码:
//根据course_id查询一条课程信息,及章节列表
router.get('/getOne',courseController.findOne,chapterController.findByCourseID,function(req,res){
var result=util.response.getInfoOK;
result.item = req.course;
result.courseitemList = req.courseitemList;
req.course = null;
req.courseitemList = null;
res.send(result);
});
这种写法看起来非常简洁,它的思路是这样的,在这个接口中,我需要调用多个controller中的方法,request、response会跟随请求依次流向这个方法,通过request把参数带过去,通过response把请求结果带过来。
现在的代码:
//申请详情
router.get('/myServiceHandleInfo', function (req, res, next) { async.auto({
rs:function(cb){ //user-server关系
serviceCtrl.getHandleRS(req.query, function (err, result) {
cb(err,JSON.parse(result));
});
},
service:function(cb){ //服务详情
console.log("sid:",req.query.sid);
serviceCtrl.getInfo({sid:req.query.sid}, function (err, result) {
console.log("service result:",result);
cb(err,JSON.parse(result));
});
},
app:function(cb){ //应用详情
appCtrl.showAppDetail(req.query.appid, function (err, result) {
cb(err,JSON.parse(result));
});
},
appUser:['app', function(results,cb) { //应用创建者详情
userCtrl.getInfo({uid:results.app.obj.did},function(err,result){
cb(err,JSON.parse(result));
})
}]
},function(err,results){
if (err) throw err;
res.send(results);
});
});
使用async之后,代码结构性和可读性都得到了改善,相信你一旦使用后,就再也不能没有它了。
对比:
1. response中参数的名称不能重复,而且response的负担特别重。async只在入口处将参数给这个方法,async请求结果是通过回调函数带过来的。
2. 方法之间是一个执行完了,才会执行下一个。而async有同步、异步、自动等多种方式。
================ =========== 开始使用Async ====== ========================
Async的内容分为三部分:
流程控制:简化常见流程的处理
集合处理:如何使用异步操作处理集合中的数据
工具类:几个常用的工具类
安装工具
npm install async --save -d
1.async.waterfall实例(多个函数依次执行,且前一个的输出为后一个的输入)
这个函数名为waterfall(瀑布),可以想像瀑布从上到下,按顺序依次执行多个函数。不同之处,每一个函数产生的值,都将传给下一个函数。如果中途出错,后面的函数将不会被执行。错误信息以及之前产生的结果,将传给waterfall最终的callback。
注意,该函数不支持json格式的tasks。
应用场景:在创建课程的接口中,首先解析表单和上传头像,然后保存课程到数据库
async.waterfall([
function(cb) {
util.formParse(req,function(err,result){ //from解析
cb(err,result);
});
},
function(user, cb) {
courseCtrl.create(course,function(err,result){ //保存到数据库
cb(err,result);
})
}
], function (err, result) {
if(err) throw err;
var results = util.response.regOK;
results.item = result;
res.send(results);
});
2.async.parallel 实例(多个函数并行执行)
并行执行多个函数,每个函数都是立即执行,不需要等待其它函数先执行。传给最终callback的数组中的数据按照tasks中声明的顺序,而不是执行完成的顺序。
如果某个函数出错,则立刻将err和已经执行完的函数的结果值传给parallel最终的callback。其它未执行完的函数的值不会传到最终数据,但要占个位置。
支持json形式的tasks,其最终callback的结果也为json形式。
应用场景:在获取课程列表接口中,要获取课程列表,同时获取课程数目
async.parallel({
count:function(cb){
courseController.count( req.query ,cb); //课程数目
},
list:function(cb){
courseController.getList( req.query ,cb); //课程列表
}
},function(err,results){
res.send(results);
});
请求结果:
{
count:2,
list:[
{
courseid:xxx,
name:xxx
},
{
courseid:xxx,
name:xxx
}
]
}
3.async.auto实例(多个函数有依赖关系,有的并行执行,有的依次执行)
用来处理有依赖关系的多个任务的执行。比如某些任务之间彼此独立,可以并行执行;但某些任务依赖于其它某些任务,只能等那些任务完成后才能执行。虽然我们可以使用async.parallel和async.series结合起来实现该功能,但如果任务之间关系复杂,则代码会相当复杂,以后如果想添加一个新任务,也会很麻烦。这时使用async.auto,则会事半功倍。
如果有任务中途出错,则会把该错误传给最终callback,所有任务(包括已经执行完的)产生的数据将被忽略。
应用场景:
根据uid(用户id)和course_id(课程id)获取用户信息和用户收藏的视频:
根据uid,在user表中获取用户信息;
根据course_id,在course表中获取课程信息,含teacher_id;
根据teacher_id,在user表中获取讲师信息(上一步执行完,才能执行);
最后,返回userInfo,courseInfo,tearcherInfo;
async.auto({
userInfo:function(cb){
userCtrl.getInfo({uid:req.query.uid}, function (err, result) { //用户信息
cb(err,result);
});
},
couseInfo:function(cb){
courseCtrl.getInfo(req.query.courseid, function (err, result) { //课程信息
cb(err,result);
});
},
tearcherInfo:['couseInfo', function(results,cb) {
userCtrl.getInfo({uid:results.couseInfo.teacherid},function(err,result){ //讲师信息
cb(err,result);
});
}]
},function(err,results){
if (err) throw err;
res.send(results);
});
请求结果:
{
userInfo:{
uid:xxx,
name:xxx
},
courseInfo:{
courseid:xxx,
name:xxx
},
tearcherInfo:{
uid:xxx,
name:xxx
}
}
GitHub代码参考地址:https://github.com/wuwanyu/async.node.test
在NodeJS中使用流程控制工具Async的更多相关文章
- Python3.7.4入门-2流程控制工具
2 流程控制工具 记得在语句后加冒号 2.1 while # Fibonacci series: # the sum of two elements defines the next a, b = 0 ...
- PYTHON 学习笔记2 流程控制工具以及函数定义、匿名函数
前言 在上一节的学习中.已经介绍了几种基本类型.包括字符串的定义,以及字符串中索引.切片.字符串拼接的使用方法.以及基本的整形数据运算.一些之前都没有了解过的运算符.比如 ** 乘方 //整数除法等. ...
- Java中的流程控制(三)
关于Java中的流程控制 关于Java中的流程控制 4.do while语句 do while语句的功能和while语句差不多,只不过它是在执行完第一次循环后才检测条件表达式的值,这意味着包含在大括号 ...
- Python基础之:Python中的流程控制
目录 简介 while语句 if 语句 for语句 Break Continue pass 简介 流程控制无非就是if else之类的控制语句,今天我们来看一下Python中的流程控制会有什么不太一样 ...
- python中的流程控制
目录 引言 流程控制的分类 分支结构 单if结构 if与else结构 if与elif与else结构 if分支的嵌套 循环结构 while循环 while + break循环 while + conti ...
- 赶紧收藏!这些Java中的流程控制知识你都不知道,你凭什么涨薪?
Java的流程控制 基础阶段 目录: 用户交互Scanner 顺序结构 选择结构 循环结构 break & continue 练习题 1.Scanner对象 之前我们学的基本语法中并没有实现程 ...
- C中的流程控制
一. 流程控制 l 顺序结构:默认的流程结构.按照书写顺序执行每一条语句. l 选择结构:对给定的条件进行判断,再根据判断结果来决定执行哪一段代码. l 循环结构:在给定条件成立的情况下,反复执行某一 ...
- Java中的流程控制(二)
关于Java程序的流程控制(二) 关于Java程序的流程控制(二) 3.switch选择语句 switch语句用于将一个表达式的值同许多其他值比较,并按比较结果选择下面该执行哪些语句. switch( ...
- Java中的流程控制(一)
程序的流程控制(一) 关于Java程序的流程控制(一) 从结构化程序设计角度出发,程序有三种结构: 顺序结构 选择结构 循环结构 1.顺序结构 就是程序从上到下一行行执行,中间没有判断和跳转. 2.i ...
随机推荐
- 本地DNS如何解析公网域名
DNS服务器图解: 为了服务于公司内部局域网应用,如域.本地网站.论坛.OA.ERP系统等,我们通常搭建本地DNS服务器. 将本地DNS服务器设置为首选DNS,本地系统解析访问是快了. 但内部DNS怎 ...
- Yii2系列教程二:MVC,Forms和Layouts
上一篇文章我们简单地实现了Yii2框架安装和Hello World,而在这一篇文章当中,我们会带着好奇之心去探索一下在Yii2中的几个重要的元素组成:MVC,Forms和Layouts. 本文的目标是 ...
- 从C转到JAVA学习路之基本知识对比(转)
转自:http://blog.csdn.net/andywxf01/article/details/53502615 我一直在用C开发,想转到Java时最容易想到的事就是把C里写的代码和功能用JAVA ...
- Java LinkedList的模拟实现
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点.查询即从第一个节点,不断指 ...
- non-compatible bean definition of same name and class
在整合struts2.1.6+spring2.5.6开发中,使用了注解和struts-convention来实现零配置管理.spring也使用注解annotation方式.现在的问题是:我在连个个不同 ...
- Java并发包——Blockingqueue,ConcurrentLinkedQueue,Executors
背景 通过做以下一个小的接口系统gate,了解一下mina和java并发包里的东西.A系统为javaweb项目,B为C语言项目,gate是本篇须要完毕的系统. 需求 1. A为集群系统,并发较高,会批 ...
- 笛卡尔树 POJ ——1785 Binary Search Heap Construction
相应POJ 题目:点击打开链接 Binary Search Heap Construction Time Limit: 2000MS Memory Limit: 30000K Total Subm ...
- 【Python3 爬虫】16_抓取腾讯视频评论内容
上一节我们已经知道如何使用Fiddler进行抓包分析,那么接下来我们开始完成一个简单的小例子 抓取腾讯视频的评论内容 首先我们打开腾讯视频的官网https://v.qq.com/ 我们打开[电视剧]这 ...
- IOS 应用程序路径
-- 获取资源文件目录 .app/下的图片,音频等资源文件 print("bundlePath" + NSBundle.mainBundle().bundlePath) //以下是 ...
- WebUI中 DataGrid多层表头 的终极解决办法
因为DataGrid控件的简单易懂,大多数做.NET程序员都喜欢用,有需要把数据显示成表格样式的地方DataGrid会是首选,但是所有的东西都会有好和不好的一面,DataGrid在给我们带来了数据显示 ...