繁体   English   中英

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

[英]Javascript async loop inside another async loop

我在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);
    });
});

但它有一些重大错误,我无法修复。

您可以使用Web Workers在后台线程中运行多个脚本。 但是并非所有浏览器都支持它们。 请参阅来自Mozilla的这篇文章或直接向Google提问: https : //developer.mozilla.org/En/Using_web_workers

您可以定期使用SetTimeout(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);

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

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与每个单词相关联。这可以很容易地做出更为整洁,但我没有时间来进行顺序处理的更整洁的版本。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM