javascript 异步循环 - asyncEach

来自

http://blog.jcoglan.com/2010/08/30/the-potentially-asynchronous-loop/

(可能已被墙)

写程序时候经常会碰到这种情况,有一个队列,对这个队列进行一次操作会相当消耗性能,因此需要对队列中每个元素独立进行操作,一个接一个。如果这个操作是阻塞的话 用一个for循环就搞定了,如果是异步操作呢。

比如,有一个url数组,需要轮流访问每一个url,上一个返回后才进行下一个

listOfUrls.forEach(function(url) {  
    $.get(url, function(response) {  
        // handle response  
    });  
});  

以上代码显然是不满足要求的,所有请求将一次发送出去,而不是一个接一个。下面介绍这样的异步forEach:

Array.prototype.asyncEach = function(iterator) {  
    var list = this,  
        n = list.length,  
        i = - 1;  
    var resume = function() {  
        i += 1;  
        if (i === n) return;  
        iterator(list[i], resume);  
    };  
    resume();  
};  

以上代码展示了这种异步模型,对于先前url数组的例子,就可以这样:

listOfUrls.asyncEach(function(url, resume) {  
    $.get(url, function(response) {  
        // handle response  
        resume();  
    });  
});  

非常漂亮,不是吗。对于异步操作来说,上面代码是没有问题的,但如果其中某些操作是同步的,在resumeiterator这两个函数不停地互相调用可能会造成堆栈溢出,解决方法是用setTimeout来迭代:

Array.prototype.asyncEach = function(iterator) {  
    var list = this,  
    n = list.length,  
    i = - 1;  
    var iterate = function() {  
        i += 1;  
        if (i === n) return;  
        iterator(list[i], resume);  
    };  
    var resume = function() {  
        setTimeout(iterate, 1);  
    };  
    resume();  
};  

setTimeout会把每次迭代操作的调用堆栈独立开,这样就不会溢出了。

 ps:虽然以上setTimeout的时间参数设为0毫秒,还会有10ms左右的延时,100次迭代就会造成1秒左右的延时,对一些苛刻要求时间的应用是一个浪费,解决方法是用setZeroTimeout代替setTimeout

这是下一篇介绍的 setZeroTimeout

转载于:https://www.cnblogs.com/aj3423/archive/2011/03/12/3150513.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值