2012-02-06 132 views
0

我在jQuery中使用each()在div中迭代子代時有一些代碼。 裏面的每個文本都被分割成單詞。每個單詞都用'for'循環處理。 此功能可能需要很長時間,並可以凍結瀏覽器,所以...在另一個異步循環內的Javascript異步循環

有沒有辦法在另一個異步循環內創建異步循環,但有人正在等待其他人完成?

有人能告訴我正確的方向嗎?

我想出了這樣的事情:

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

我確定有一個解決方案,但是如果沒有看到實際的代碼和更多關於您想要更改的代碼的具體描述,我們無法真正幫助您。 – jfriend00 2012-02-06 23:19:20

回答

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); 
+0

Jacob不應該將'setTimeout'函數的參數顛倒過來,以便函數先傳遞,然後延遲?然後它會讀爲'setTimeout(processItemFromQueue,delayBetweenItems);'。參考[MDN setTimeout()](https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers.setTimeout) – Ash 2014-12-24 00:16:22

+0

是的,感謝您的更正,@Ash。定影。 – Jacob 2014-12-25 20:51:56

1

您可以使用SetTimeout(0,...)定期向「產量」控制瀏覽器,以防止凍結瀏覽器(但不會執行任何快,事實上它可能會稍微慢一點)。

查看this answer作爲技術的一個例子,我不能沒有看到你的代碼更具體。你可以這樣做

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

可以重寫,這樣做既外(i)和內部(J)與setTimeout()循環:

// 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正確的價值觀,但我不」沒有時間做一個整潔的版本,按順序處理。)