2012-04-13 68 views
0

我使用的插件代碼張貼在:如何將kill方法添加到現有的jQuery插件?

jQuery Tips and Tricks

...這是essentailly異步定時循環:

jQuery.forEach = function (in_array, in_pause_ms, in_callback) 
{ 
    if (!in_array.length) return; // make sure array was sent 

    var i = 0; // starting index 

    bgEach(); // call the function 

    function bgEach() 
    { 
     if (in_callback.call(in_array[i], i, in_array[i]) !== false) 
     { 
      i++; // move to next item 

      if (i < in_array.length) setTimeout(bgEach, in_pause_ms); 
     } 
    } 

    return in_array; // returns array 
}; 


jQuery.fn.forEach = function (in_callback, in_optional_pause_ms) 
{ 
    if (!in_optional_pause_ms) in_optional_pause_ms = 10; // default 

    return jQuery.forEach(this, in_optional_pause_ms, in_callback); // run it 
}; 

與這個偉大社會的幫助下,我學會了如果我「迴歸真理」或「返回false」;它與循環的下一次迭代有相同的影響。

我想要做的也是以編程方式完全kill(銷燬)$ .forEach循環調用,而不允許剩餘的迭代運行。

我該如何向此插件添加一個方法,以允許我在不影響同時運行調用的其他調用的情況下終止對插件的特定調用?

我想過像這樣將該呼叫分配給一個變量:

var foo = $.forEach(json, 1000, function(idx,item) { /* do stuff */ }); 

...後來引用具體事例,而不會影響其他人,但我怎麼添加一個殺法,並調用它FOO ?我需要和ajax調用一樣的foo.abort()。

可以這樣做嗎?如果是這樣,怎麼樣?

回答

0

這實際上只是示例代碼,所以它有一些問題。

你可以通過簡單地增加一個expando屬性的in_array對象緩解這樣的:

jQuery.forEach = function (in_array, in_pause_ms, in_callback) 
{ 
    // Note, you should use $.isArray(), which is smarter than checking length. 
    if (!$.isArray(in_array)) return false; 
    in_array.valid = true; 
    var i = 0; // starting index 
    function bgEach() 
    { 
     if (!in_array.valid) return; 
     if (in_callback.call(in_array[i], i, in_array[i]) !== false) 
     { 
      i++; // move to next item 

      if (i < in_array.length) setTimeout(bgEach, in_pause_ms); 
     } 
    } 

    // I moved this because you were calling it before it was defined. 
    bgEach(); // call the function 
    return in_array; // returns array 
}; 

既然你從方法獲得的原始數組對象回來,你可以設置的「有效」屬性對象爲假時,即可大功告成:

var foo = $.forEach(json, 1000, function(idx,item) { /* do stuff */ }); 
foo.valid = false; 

由於valid財產取消的setTimeout遞歸,這將有效地殺滅循環。

請注意,這種代碼有點危險。你會遇到競爭條件和什麼,但是當你開始在JS中使用僞線程&異步代碼時會發生這種情況。

+0

@約翰格林 - 你能解釋比賽條件嗎?我實現了這個功能以避免與$ .each或for循環相關的UI鎖定,但想知道使用這種方法的危險。非常感謝。 – Inator 2012-04-13 02:42:33

+0

那麼,你正在運行一個項目隊列,而且你一次只能調用一個項目。如果你不得不通過你的數組尋找其他功能,你可能會在某種情況下切換狀態,但它已經排隊等待在異步數組中切換。 通常,您的第一個業務順序應該是優化您的查詢和關閉,儘管您總是可能需要這樣的隊列。根據我的經驗,我發現有99%的人希望實現像這樣的應該只是優化他們的代碼。 – 2012-04-13 09:09:15

-1

你可以通過定時器步入回調,改變

if (i < in_array.length) setTimeout(bgEach, in_pause_ms); 

if (i == in_array.length) clearTimeout(timeout); 

這將保證它只會循環多次,有物品。

這裏是jQuery的的forEach:

jQuery.forEach = function (in_array, in_pause_ms, in_callback) 
{ 
    if (!in_array.length) return; // make sure array was sent 

    var i = 0; // starting index 

    bgEach(); // call the function 

    function bgEach(){ 
     var timeout; 
     if (in_callback.call(in_array[i], i, in_array[i], timeout = setTimeout(bgEach, in_pause_ms)) !== false) 
     { 
      i++; // move to next item 
      // if end of array, stop iterating 
      if (i == in_array.length) clearTimeout(timeout); 
     } 
    } 

    return in_array; // returns array 
}; 

您可以使用它來清除定時器如果滿足一定的標準,從而結束循環。例如:

$.forEach([1,2,3], 1000, function(idx, item, timer) { 
    if(item == 2) { 
    clearTimeout(timer); 
    } 
});