最近项目中遇到了一个功能,会涉及到不少并发的请求,但是公司浏览器又不支持Promise、async/await,正好趁此机会总结一下有关异步请求的处理方式。
简化下项目中实际遇到的问题,去掉其他的逻辑:
有一个最终包含n个子节点的xml对象
<rules>
<rule1>....</rule1>
<rule2>....</rule2>
<rule3>....</rule3>
.....
<rulen>....</rulen>
</rules>
需要遍历每个子节点,每次遍历到这个节点的时候,利用包括这个节点以及其prev的节点作为一个xml规则,去异步请求,最终拿到所有异步的结果去进行下面的逻辑。
再简化下,
遍历一个数组,拿每一项作为参数去异步请求
var arr = [1,2,3,4,5,6,7,8,9];
需求:因为JS事件循环的机制,后续执行的同步代码的需要之前所有异步操作的结果
方案一:并行改串行
最简单的方法就是用回调,将每次的异步操作分别放到之前异步的回调里:
function async1(){
async2()
}
function async2(){
//....
}
async1();
优点:简单
缺点:总执行时间是所有异步请求累加,可能会很长
方案二:用一个变量来计数
function async1(){
callback()
}
function async2(){
callback()
}
function callback(){
cnt++
if(2==cnt){
console.log('都执行完毕')
}
}
方案三:在方案二中不用回调计数,用定时器计数
var cnt = 0;
function async1(){
cnt++
}
function async2(){
cnt++
}
var interval = setInterval(function(){
if(cnt==2){
console.log("执行完毕")
clearInterval(interval);
}
})
缺点:定时器占用CPU较多
方案四:jquery的Deferred
var d1 = $.Deferred();
var d2 = $.Deferred();
function async1(){
d1.resolve( "Fish" );
}
function async2(){
d2.resolve( "Pizza" );
}
$.when( d1, d2 ).done(function ( v1, v2 ) {
console.log( v1 + v2 + '已完成');
});