Async 异步转同步
前要:今天写react的一对多视频会议的项目时,4秒刷新一次会议成员,每一次4秒重新请求接口的时候,正在会议的成员的视频有的重新加载!就想到4秒刷新的时候获取回来的数组进行和视图的数组进行对比,有改变就会默默刷新掉对应的参数,静默更新状态而不影响当前正在视频的会议!
Async的内容主要分为三部分
- 流程控制: 简化九种常见的流程的处理
- 集合处理:如何使用异步操作处理集中的数据
- 工具类:几个常用的工具类
本文主要介绍流程控制部分,后续内容持续更新,由于node.js是异步编程模型,有许多在同步编程中很容易做到的事情,现在就会变的很麻烦,并且存在很多的callback。但是,Async的流程控制给我们coder带来了许多便利。
1.series(task, [callback])(多个函数依次执行,之间没有数据交换)
有多个异步函数需要依次调用,一个完成之后才能执行下一个。各函数之间没有数据交换,仅仅需要保证其顺序执行。这时可以使用series。
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的详细解释为
- 依次执行一个函数数组中的每个函数,每一个函数执行完成之后才能执行下一个函数。
- 如果任何一个函数向它的回调函数中传了一个error,则后面的函数都不会被执行,并且将会立刻将该error以及已经执行了的函数的结果,传给series中最后的那个callback。
- 将所有的函数执行完后(没有出错),则会把每个函数传给其回调函数的结果合并为一个数组,传给series最后的那个callback。
- 还可以以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中的不足
例如我要完成下面的事情
- 从某处取得数据
- 在硬盘上建立一个新的目录
- 将数据写入到目录下某文件
- 发送邮件
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']
})
Async 异步转同步相关推荐
- ajax中异步属性,ajax中的async属性值之同步和异步及同步和异步区别
jquery中ajax方法有个属性async用于控制同步和异步,默认是true,即ajax请求默认是异步请求,有时项目中会用到AJAX同步.这个同步的意思是当JS代码加载到当前AJAX的时候会把页面里 ...
- async await 处理异步变同步(微信小程序内举例)
1.async起什么作用? 输出的是一个Promise对象 注: 1)async函数返回的是一个Promise对象.Async函数(包含函数语句.函数表达式.Lambda表达式)会返回一个Prom ...
- ajax异步详解同步请求,ajax async异步请求和同步请求
ajax async异步请求和同步请求 ajax是指异步加载.这个异步是相对于页面来说的,页面不刷新就加载服务器数据.ajax中的请求又分为同步请求和异步请求,这里是相对于进程来说的,ajax异步请求 ...
- Node.js模拟发起http请求从异步转同步的5种方法
使用Node.js模拟发起http请求很常用的,但是由于Node模块(原生和第三方库)提供里面的方法都是异步,对于很多场景下应用很麻烦,不如同步来的方便.下面总结了几个常见的库API从异步转同步的几种 ...
- 使用@Async异步注解导致该Bean在循环依赖时启动报BeanCurrentlyInCreationException异常的根本原因分析,以及提供解决方案
前言 今天在自己工程中使用@Async的时候,碰到了一个问题:Spring循环依赖(circular reference)问题. 或许刚说到这,有的小伙伴就会大惊失色了.Spring不是解决了循环依赖 ...
- object转class_从零并发框架(三)异步转同步注解+字节码增强代理实现
序言 上一节我们学习了异步查询转同步的 7 种实现方式,今天我们就来学习一下,如何对其进行封装,使其成为一个更加便于使用的工具. 思维导图如下: 异步转同步字节码增强 拓展阅读 java 手写并发框架 ...
- js:nodejs通过async异步提交事务数据
一,async异步编程 1,异步编程是指由于异步I/O等因素,无法同步获得执行结果时, 在回调函数中进行下一步操作的代码编写风格,常见的如setTimeout函数.ajax请求等等 waterfall ...
- forEach、map、for..of、for..in、for循环实现异步变同步的问题
一.背景 开发中经常遇到,遍历去查询服务获取数据,并且后边的代码需要借用上边查询到的数据,但是查询服务是一个异步操作,运用forEach或者map循环,在还没有查询到数据后,就执行了下一步操作,所以以 ...
- 微信小程序异步转同步的解决方法
一.前言 二. promise的概念 三.promise的使用 四.一个因为异步请求出问题的案例 五.案例的解决方案 1.运用promise解决异步转同步问题 2.运用async+await+prom ...
最新文章
- kind富文本编辑器_富文本编辑器原理探索
- 【100】新学年的学习安排
- shell 全局和局部变量
- vue-router 路由嵌套显示不出来_网络协议|OSI模型第三层网络层中的路由
- 95-910-165-源码-FlinkSQL-Flink SQL 中的时间属性
- JMV监控工具之JConsole
- 营收增长“疫”外超预期,走向手游化的动视暴雪能否弯道超车?
- 扫描仪显示没有服务器,扫描仪安装好了,点击显示寻找扫描仪怎么显示未找出扫描仪...
- 二十一世纪大学英语读写基础教程学习笔记(原文)——4 - The Happiest Man in the World(世界上最幸福的人)
- 开源中国正式进军软件开发众包领域
- 谷歌 draco学习 一 压缩格网信息
- USB网卡收发数据分析
- 将jmeter响应结果中部分数据保存到本地文件
- 奇葩!小米手机自带浏览器css兼容问题,强制屏蔽、隐藏类名为 top_box 的元素。
- php configure 报错 error: xml2-config not found. Please check your libxml2 installation
- h5发送短信以及判别用户浏览器版本
- 【Pytorch学习】torch.mm()torch.matmul()和torch.mul()以及torch.spmm()
- 使用的tk集成mybatis,报No MyBatis mapper was found in的警告解决方案
- 【博学谷学习记录】超强总结,用心分享 | 【Java】 Maven
- 联想Y400win10基础上在安装win7
热门文章
- #Linux#进程间通信# 管道(pipe)-标准流管道pipe
- JAVA 冷知识( break outer ;)
- ABAP 设置ALV复选框
- 前端框架React Js入门教程【转】
- 首家区块链上市公司 他们为金融机构量身定做的区块链底层基础设施
- 两种include方式的作用
- Java十六:Scanner,配合hasNext()/hasNextInt()/hasNextFloat()....实现人机互动
- L1正则化和L2正则化(从解空间角度)
- Selective Search原理及实现
- Excel提取身份证出生日期②