2015-05-29 37 views
1

在等待後端開發人員實現取消所有後端跟蹤任務的「取消全部」功能時,我試圖通過取消每個單獨的任務來進行調整。取消REST服務接受數據對象{transferID: someID}形式的ID。使用相同數據延遲Ajax調用相同的URL

我使用FOR循環遍歷我已存儲在別處的ID數組。預計人們可能會完成數十或數百個任務,但我希望實現一個小的延遲,理論上這並不會使瀏覽器可以處理的HTTP請求數量溢出,並且還會減少後端CPU的負載。下面是一些代碼,使本次討論的目的評論:

ta.api.cancel = function (taskArray, successCallback, errorCallback) { 
// taskArray is ["task1","task2"] 

// this is just the latest attempt. I had an attempt where I didn't bother 
// with this and the results were the same. I THOUGHT there was a "back image" 
// type issue so I tried to instantiate $.ajax into two different variables. 
// It is not a back image issue, though, but one to do with setTimeout. 
ta.xhrObjs = ta.xhrObjs || {}; 


for (var i = 0; i < taskArray.length; i++) { 
    console.log(taskArray); // confirm that both task1 and task2 are there. 

    var theID = taskArray[i]; 
    var id = {transferID: theID}; // convert to the format understood by REST 

    console.log(id); // I see "task1" and then "task2" consecutively... odd, 
    // because I expect to see the "inside the setTimeout" logging line next 

    setTimeout(function() { 
     console.log('inside the setTimeout, my id is: ') 
     console.log(id.transferID); 
     // "inside the setTimeout, my id is: task2" twice consecutively! Y NO task1? 

     ta.xhrObjs[theID] = doCancel(id); 
    }, 20 * i); 
    } 

    function doCancel(id) { 
    // a $.Ajax call for "task2" twice, instead of "task1" then "task2" 20ms 
    // later. No point debugging the Ajax (though for the record, cache is 
    // false!) because the problem is already seen in the 'setTimeout' and 
    // fixed by not setting a timeout. 
    } 
} 

事情是:我知道的setTimeout使含有功能異步執行。如果我沒有超時,只需在迭代器中調用doCancel,它將在task1然後task2上調用它。但雖然它使呼叫異步,我不明白爲什麼它只是task2兩次。我的頭不能纏繞它。

我正在尋找一種方法來讓迭代器以20ms的延遲進行Ajax調用。但我需要它來呼籲!有人看到我可以修復的明顯錯誤,或者知道一種技術?

+0

什麼是'jobArray' ...應該是'taskArray'? –

+1

在它們的作用範圍的函數開始處聲明變量。不僅如此,JS將如何運行你的程序(提升),它應該幫助你看到什麼是(關閉var ID)。 – Malk

+1

我認爲你有問題的直接原因是當你在'setTimeout'內使用一個變量時,它不會將變量'凍結'到'setTimeout'聲明時的值。相反,當'setTimeout'回調調用實際發生時,它將評估var。你需要創建一個閉包http://stackoverflow.com/questions/10217536/how-to-pass-a-variable-into-a-settimeout-function –

回答

1

,必須用你的函數setTimeout和id變量傳遞到它,就像這樣:

(function(myId, i) { 
    setTimeout(function() { 
     console.log('inside the setTimeout, my id is: ', myId); 
    }, 20 * i); 
}(theId, i)); 
+0

訣竅漂亮。謝謝,何塞。 –

+0

歡迎您:) –

1

這種模式不適合作爲人們所預料的循環的每個實例創建一個唯一variable1

function() { 
    for (var i = 0; i < length; i++) { 
     var variable1; 
    } 
} 

在JavaScript變量被「懸掛」。引用的Mozilla:

「因爲變量聲明(和聲明通常)被執行的任何代碼之前 處理,在代碼聲明一個變量的任何地方 相當於在頂部它聲明」

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var

所以應該重新寫爲:

function() { 
    var variable1; 
    for (var i = 0; i < length; i++) { 
    } 
} 

這意味着該循環結束後,引用此變量的任何異步回調將看到的最後的值的循環。

+0

看起來比這更多。如果我在for循環之外聲明一個變量,然後在for循環中更新它,最後一個值仍然用於setTimeout。我需要更新for循環中的變量,因爲它在每次迭代時都會更改。如果我在進入for循環之前有辦法更新它,我認爲這樣可以;但是,迭代器的全部要點是在索引處獲取新值。 –

+0

你說得對。你需要處理這個問題來獲得你所需要的。檢查Jose Mato的回答。它使用立即執行的函數表達式來「鎖定」每個迭代的唯一變量。 – Malk