专栏首页OECOMnodejs之async模块

nodejs之async模块

async模块是为了解决嵌套金字塔,和异步流程控制而生,常用方法有series、parallel、waterfall、parallelLimit、auto、whilst、doWhilst、forever和compose,下面分别对这几种方式进行介绍

series

多个函数从上到下依次执行,相互之间没有数据交互,调用方法为series(task,[callback])

var task1 = function(callback){
		console.log("task1");
		callback(null,'task1')
	}
	var task2 = function(callback){
		console.log("task2");
		setTimeout(()=>{
			callback(null,'task2')
		},5000)
		
	}
	var task3 = function(callback){
		console.log("task3");
		callback(null,'task3')
	}
	async.series([task1,task2,task3],function(err,result){
		console.log('series');
		if(err){
			console.log(err);
		}
		console.log(result);
	})

输出结果为

如果中途发生错误,则将错误传递到回调函数,并停止执行后面的函数

var task1 = function(callback){
		console.log("task1");
		callback(null,'task1')
	}
	var task2 = function(callback){
		console.log("task2");
		setTimeout(()=>{
			callback('err','task2')
		},5000)
		
	}
	var task3 = function(callback){
		console.log("task3");
		callback(null,'task3')
	}
	async.series([task1,task2,task3],function(err,result){
		console.log('series');
		if(err){
			console.log(err);
		}
		console.log(result);
	})

输出结果为

parallel

多个函数并行执行,不会等待其他函数,调用方式parallel(tasks,[callback])

var task1 = function(callback){
		console.log("task1");
		setTimeout(()=>{
			callback(null,'task1')
		},4000)
	}
	var task2 = function(callback){
		console.log("task2");
		setTimeout(()=>{
			callback(null,'task2')
		},5000)
		
	}
	var task3 = function(callback){
		console.log("task3");
		setTimeout(()=>{
			callback(null,'task23')
		},2000)
	}
	console.time("parallel方法");
	async.parallel([task1,task2,task3],function(err,result){
		console.log('parallel');
		if(err){
			console.log(err);
		}
		console.timeEnd("parallel方法");
		console.log(result);
	})

输出结果为:

如果中途出错,则立即将err和值传到最终的回调函数,其他未执行完毕的函数将不再执行,但是要占一个位置

也就是说如果第二个方法抛出错误,则返回的数组为['task1','task3']

waterfall

依次执行,前一个函数的输出为后一个函数的输入,这是使用最多的一个方法,解决多个异步嵌套很是方便。具体调用方式为:waterfall(tasks,[callback])

var task1 = function(callback){
		console.log("task1");
		callback(null,'11')
	}
	var task2 = function(params,callback){
		console.log("1传递过来的参数:"+params);
		setTimeout(()=>{
			callback(null,'22')
		},5000)
		
	}
	var task3 = function(params,callback){
		console.log("task3");
		console.log("2传递过来的参数:"+params);
		setTimeout(()=>{
			callback(null,'33')
		},2000)
	}
	async.waterfall([task1,task2,task3],function(err,result){
		console.log('waterfall');
		if(err){
			console.log(err);
		}
		console.log(result);
	})

输出结果为

如果中途出现错误,后面的函数将不在执行,之前执行的结果和错误信息将直接传到最终的回调函数,在此不再赘述。

parallelLimit

这个方法和parallel类似,只是limit参数限制了同时并发执行的个数,不再是无限并发,调用方法为:parallelLimit(tasks,limit,[callback])

var task1 =function(callback){
 
		console.log("task1");
		setTimeout(function(){
			callback(null,"task1")
		},5000);
		
	}
 
	var task2 =function(callback){
 
		console.log("task2");
 
		setTimeout(function(){
			callback(null,"task2")
		},3000);
	}
 
	var task3 =function(callback){
 
		console.log("task3");
		setTimeout(function(){
			callback(null,"task3")
		},4000);
	}
	console.time("parallelLimit方法");
	async.parallelLimit([task1,task2,task3], 2, function(err,result){
 
		console.log("parallelLimit");
 
		if (err) {
			console.log(err);
		}
 
		console.log(result);
		console.timeEnd("parallelLimit方法");
	})

运行结果为

看到上面执行时间有的人会问了,为什么三个任务分别执行时间为5s,4s,3s,为何执行结果不是5s而是七秒呢,原因就在于并发上了,先执行了1和2两个任务,在4s的时候2任务执行完成,此时开始执行3任务,同时1任务还差1秒执行完成,如此总的时间就变成了7秒。

auto

多个函数有数据交互,有的并行,有的依次执行,调用方法:auto(tasks,[callback])

console.time("auto方法");
async.auto({
task1: function(callback){
console.log("tsak1");
setTimeout(function(){
callback(null, 'task11', 'task12');
},2000);
},
task2: function(callback){ 
console.log('task2');
setTimeout(function(){ 
callback(null, 'task2');
},3000);
},
task3: ['task1', 'task2', function(results,callback){
console.log('task3');
console.log('task1和task2运行结果: ',results);
setTimeout(function(){ 
callback(null, 'task3');
},1000);
}],
task4: ['task3', function(results,callback){
console.log('task4');
console.log('task1,task2,task3运行结果: ',results);
setTimeout(function(){
callback(null, {'task41':results.task3, 'task42':'task42'});
},1000);
}]
}, function(err, results) {
console.log('err :', err);
console.log('最终results : ', results);
console.timeEnd("auto方法");
});

运行结果为:

5秒运行完毕,

函数1和2并行,3秒执行完毕,

函数1和2执行完毕后,函数3,4依次执行共计5秒.

whilst

相当于while循环,fn函数里不管是同步还是异步都会执行完上一次循环才会执行下一次循环,对异步循环很有帮助,

test是条件,为true时执行fn里的方法

var datalist = [{number:10},{number:20},{number:30},{number:40},{number:50}];
	var count = 0;
 
	var test = function () {
		return count<datalist.length;
	};
 
	var fn = function(callback){
		console.log(datalist[count].number);
		setTimeout(function () {
			count++;
			callback();
		},1000)
	};
	
	async.whilst(test,fn,function(err){
		if(err){
			console.log(err);
		}
		console.log('whilst结束');
	});

doWhilst

和whilst类似,和do-while一个意思,首先执行一次fn,再判断,和whilst相比它把fn和test位置交换了而已.

until和whilst相反,当test判断为false的时候执行fn里的方法,为true时跳出,

doUntil与doWhilst相反.

forever

forever就是无限循环了.只有当中途出现错误的时候才会停止,调用方法forever(fn,errback)

var count = 0;
  async.forever(function(callback){
  	console.log(count);
  	count++;
 
  	if (count>10) {
  		callback("errmessage");
  		return;
  	}
 
  	setTimeout(function () {
  		callback();
  	},1000)
  },
  function(err){
  	console.log(err);
  });

compose

这个方法会创建一个异步的集合函数,执行的顺序是倒序.前一个fn的输出是后一个fn的输入.有数据交互,调用方法:compose(fn1,fn2,fn3...)

var task1 =function(m,callback){
 
		console.log("task1");
		setTimeout(function(){
			callback(null,m*2)
		},1000);
		
	}
 
	var task2 =function(m,callback){
 
		console.log("task2");
 
		setTimeout(function(){
			callback(null,m+3)
		},1000);
	}
 
	var task3 =function(m,callback){
 
		console.log("task3");
		setTimeout(function(){
			callback(null,m*5)
		},1000);
	}
	console.time("compose方法");
 
	var com = async.compose(task3,task2,task1);
 
	com(2,function(err,result){
		if (err) {
			console.log(err);
		}
		console.log(result);
		console.timeEnd("compose方法");
	})

运行结果

相当于 var m=2; (m*2+3)*5 =35;

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 函数与变量的优先级

    我们之前说过变量声明会出现变量提升的情况,这个问题说的已经很多了,但是我还是想在啰嗦一下。直觉上我们都会认为 JavaScript 是单线程语言,代码在执行时是...

    无邪Z
  • js检测代码段执行时间

    有时为了优化代码执行效率需要知道一段代码执行花费的总时间,在js中通过console.time()和console.timeEnd()即可获得,例如:

    无邪Z
  • nodejs操作mysql数据库

    nodejs是一个运行在服务器端的JavaScript框架,既然是在服务器端运行,就少不了需要操作数据库。在nodejs中提供了一个基本的mysql模块,同时本...

    无邪Z
  • xilinx verilog 语法技巧

    在Vivado Design Suite中,Vivado综合能够合成多种类型的属性。在大多数情况下,这些属性具有相同的语法和相同的行为。

    FPGA开源工作室
  • 用NW.js构建跨平台桌面应用(4)-数据持久化

    https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API

    江米小枣
  • RabbitMQ性能测试

    作者一直在寻找一个极低延时的消息队列,从目前的测试结果来看,只有nats达到了<1ms的水平,本文旨在测试rabbitmq的国latency,撰文记录并与大家分...

    王亚昌
  • JavaScript Event Loop 机制详解与 Vue.js 中实践应用

    JavaScript 是典型的单线程单并发语言,即表示在同一时间片内其只能执行单个任务或者部分代码片。换言之,我们可以认为某个同域浏览器上下中 JavaScri...

    前端博客 : alili.tech
  • 再谈谈数学

      在一个很老的群里聊天,群里就那么二十几个人,都是搞这行的,在网上认识了十几年。一人是某大型电子地图公司出来的,说,”地图里面人工智能不就是用初中的概率论搞起...

    窗户
  • async简单使用

           node的异步io虽然好用,但是控制异步流程确实一个比较麻烦的事情,比如在爬虫中控制并发数量,避免并发过大导致网站宕机或被加入黑名单。因此需要一个...

    用户2038589
  • 内网渗透Tips

    https://github.com/Ridter/Intranet_Penetration_Tips

    HACK学习

扫码关注云+社区

领取腾讯云代金券