如何使用underscore.js进行屈服循环?

时间:2013-06-20 13:57:48

标签: javascript underscore.js settimeout

所以,我想循环遍历数百个项目,而不是在我处理每个项目时阻止UI线程 - 总共可能需要几秒钟的工作,所以我想经常收益。几本书推荐了一个如下所示的循环:

function processArray(items, process, callback){
    var todo = items.concat(); //create a clone of the original
    setTimeout(function () {
        process(todo.shift());
        if (todo.length > 0) {
            setTimeout(arguments.callee, 100);
        } else {
            callback(items);
        }
    }, 100);
}

(参考http://answers.oreilly.com/topic/1506-yielding-with-javascript-timers/

上次我使用了一个聪明的循环,我发现下划线已经支持它,并且可能有更好,更稳定等版本。如何在下划线中执行上述操作? _.each似乎不适用,_.each似乎不会产生或提供更改暂停时间的选项。

2 个答案:

答案 0 :(得分:2)

查看异步库
https://github.com/caolan/async
并使process成为一个接受回调的异步函数。

function process(item, cb){
    //replace this code block with your actual process logic
    setTimeout(function () {console.log(item); async.nextTick(cb);}, 500);
}
function processArray(items, iterator, callback){
    var todo = items.concat(); //create a clone of the original
    async.eachLimit(todo, 4, iterator, function(){ 
        //replace 4 with the desired number of simultaneous asynchronous operations
        //if `process` isn't too computationally expensive, you could try 50 
        callback(); //all done
    });
}

processArray([0,1,2,3,4,5,6,7,8,9,10], process, function(){
    console.log('all done');
});

演示:http://jsbin.com/izumob/1/

答案 1 :(得分:0)

我建议您改用间隔。这样,您不会反复调用setTimeout,也不会在每次迭代时构建匿名函数:

function processArray(items, process, callback) {
  var todo = items.concat();

  //our interval "loop"
  var loop = setInterval(function () {

    process(todo.shift());

    //"break" the interval when nothing left
    if(!todo.length) {
      clearInterval(loop);
      callback(items);
    }
  }, 100);
}