另一个异步循环中的Javascript异步循环

时间:2012-02-06 23:09:06

标签: javascript jquery

我在jQuery中有一些代码使用each()遍历div中的子代。 里面的每个文本都被分成了单词。每个单词都用'for'循环处理。 此功能可能需要很长时间,因此可以冻结浏览器......

有没有办法在另一个异步循环中创建异步循环,但是有人在等待其他循环完成?

有人能告诉我正确的方向吗?

我想出了类似的东西:

var queue = [];
var nlevel = 0;

function work() {
    nlevel = queue.length-1;

    var arr = queue[nlevel][0];
    var process = queue[nlevel][1];
    var cnt = queue[nlevel][2];
    var item = arr[cnt];

    process.apply(item);

    cnt++;
    queue[nlevel][2] = cnt;

    if (cnt < arr.length) {
        setTimeout(work, 1);
    } else {
        if (queue.length>1) {
            queue.pop();
            setTimeout(work, 1);
        }
    }
}

function each(arr, process) {
    queue.push([arr, process, 0]);

    setTimeout(work, 1);
}


each(['one', 'two', 'three'], function() {
    alert(this);

    each([1, 2, 3, 4], function() {
        alert(this);
    });
});

但它有一些重大错误,我无法解决它。

4 个答案:

答案 0 :(得分:3)

您可以使用Web Workers在后台线程中运行多个脚本。但是在每个浏览器中都不支持它们。请参阅Mozilla的这篇文章或简单问Google:https://developer.mozilla.org/En/Using_web_workers

答案 1 :(得分:1)

您可以定期使用SetTimeout(0,...)来“控制”浏览器控制,以防止冻结浏览器(但它不会执行得更快,实际上它可能会稍慢)。

有关该技术的示例,请参阅this answer,如果没有看到您的代码,我就无法更具体。

答案 2 :(得分:0)

您可以这样做的一种方法是创建要处理的工作项队列:

var queue = [];

将要处理的项目放在此队列中,而不是立即处理:

queue.push(item);

然后启动一个定时器循环来处理项目:

var delayBetweenItems = 10;
var processItemFromQueue = function() {
    if (queue.length) {
        item = queue.shift();
        doStuff(item);
        setTimeout(delayBetweenItems, processItemFromQueue);
    }
};
setTimeout(processItemFromQueue, delayBetweenItems);

答案 3 :(得分:0)

假设您当前的代码类似于此:

function processWord(word, i, j) {
   // do something with the current word, where
   // (if it's needed) i is the index into the elements
   // and j is the index into the current element's words
}

$("#divId").children().each(function(i) {
    var words = $(this).text().split(" "),
        j;
    for(j = 0; j < words.length; j++) {
       processWord(words[j], i, j);
    }
});

你可以用setTimeout()重写那个外部(i)和内部(j)循环:

// assumes the same processWord() function as above

(function (){
    var $items = $("#divId").children(),
        words,
        i, j,
        iMax, jMax;

    function doIteration() {
       if (j === jMax) {
          if (++i === iMax)
             return;

          // outer loop processing
          words = $($items[i]).text().split(" ");
          jMax = words.length;
          j = 0;
       }
       if (j < jMax) {
          // inner loop processing
          processWord(words[j], i, j);
          j++;
       }

       setTimeout(doIteration, 1);
    }

    iMax = $items.length;
    i = j = jMax = -1;
    doIteration();
})();

工作演示:http://jsfiddle.net/sp8Wr/

doIteration()函数通过适当处理一些计数器并通过setTimeout()调用自身来进行下一次迭代来模拟嵌套循环。包含整个事物的立即执行的匿名函数对于该过程来说并不重要,它只是限制变量的范围。

是的,这可能会做得更好,但这正是我动态想出的 - 显然你会根据自己的处理进行修改。

(只要processWord()函数获得与每个单词关联的ij的正确值,您就不在乎处理单词的处理顺序可以很容易地使很多更整洁,但我没有时间做一个整洁的版本按顺序处理。)