![](/img/trans.png)
[英]Why does the setTimeout callback wait for the end of the loop when the timer is 0ms?
[英]Why does Javascript say "callback is not a function" in setTimeout when the wait value is much lower?
我已經用 javascript 編寫了一個基本的工作運行程序(也使用了一些 JQuery,但這是另一天的另一個故事),我遇到了這個奇怪的問題:
我運行以等待所有作業完成的方法:
$.getAllProducts = function(callback){
$.getProductDetails('|ALL|', function(allProductsResult){ //intentionally
var objAllProducts = JSON.parse(JSON.parse(allProductsResult));
var objProductsBuiltUp = {};
var productLength = objAllProducts.length;
$.totalJobs(productLength);
var processed = 0;
$.completedJobs(processed);
$.each(objAllProducts, function(i,v){
$.getProductDetails(objAllProducts[i].ProductCode, function(result){
$.mergeShallow(objProductsBuiltUp, JSON.parse(JSON.parse(result)));
processed++;
$.completedJobs(processed);
});
});
$.wait(0, false, function(isDone){ //allow at least 50ms wait time, otherwise this confuses javascript into thinking there are no callbacks
if (isDone){
callback(objProductsBuiltUp.ProductComponents);
}
});
});
}
作業的處理程序
$.checkProgress = function() {
return $.jobs === $.completed;
}
$.totalJobs = function(total) {
$.jobs = total;
}
$.completedJobs = function(completed) {
$.completed = completed;
}
$.wait = function(timeout, debug, callback) {
setTimeout(function() {
if (debug) {
console.log($.completed + " / " + $.jobs + " = " + ($.completed / $.jobs * 100) + "%");
}
if ($.checkProgress() == false) {
$.wait(timeout, debug);
}
callback($.checkProgress()); // <-- complaining one
}, timeout);
}
這是我的小作業運行器的關鍵點代碼,其他方法將調用$.totalJobs()
來設置需要執行的作業數量(通常根據需要對 API 進行不同調用的數量在我的場景中) ) 和$.completedJobs()
- 在 API 處理程序的回調中返回有效負載時調用
問題是,當我將“服務員”設置為 50 毫秒時,我沒有收到任何錯誤,並且該方法按預期執行。
當我將它設置為 5ms、1ms、0ms 等低值時,它告訴我:
“xxxxx.helpers.js:48 未捕獲的類型錯誤:回調不是函數”
任何人都有一個瘋狂的理論為什么會發生這種情況? 畢竟,它只是一個美化的setTimeout
。
(為了回應為什么我使用 JQuery 全局方法和變量來存儲信息,是為了讓我自己更輕松地使用 Meteor,因為知道它已加載到 1 個地方 - 這是我目前正在開發的平台。)
編輯對我來說更好地添加運行回調的整個方法
看起來你沒有在這里傳遞回調:
$.wait = function(timeout, debug, callback) {
//code here
if ($.checkProgress() == false) {
$.wait(timeout, debug); // === $.wait(timeout, debug, undefined);
}
callback($.checkProgress()); // <-- complaining one
}, timeout);
所以如果$.checkProgress()
是假的,你遞歸調用$.wait
只有callback
是undefined
......
乍一看,我認為你想在那里寫的是:
$.wait(timeout, debug, callback); // pass callback argument to inner call
但顯然,您不想多次調用回調:
$.wait = function(timeout, debug, callback) {
//code here
if ($.checkProgress() == false) {
$.wait(timeout, debug, callback);
} else {
callback($.checkProgress());
}
}, timeout);
您標記為“抱怨者”的行實際上是在抱怨的原因是因為它是遞歸調用。 $.checkProgress
評估為 false,調用$.wait
函數(這次, callback
未定義),並一直持續到$.checkProgress() === false
評估為 false。 然后, callback
( undefined
)將在內部調用中被調用。
當間隔減少時,這個問題開始出現。 這是有道理的,因為如果作業尚未完成,您只會遞歸調用$.wait
。 超時/間隔越高,第一次完成作業的機會就越大。
通過減少間隔,您到達了在作業完成之前調用$.wait
的點,並且您進入了$.checkProgress() === false
分支,調用$.wait
而不傳遞回調(基本上丟失了一個引用到它)。
當作業完成時,您正在嘗試調用設置為undefined
callback
m 。
在
if ($.checkProgress() == false) { $.wait(timeout, debug); }
您沒有傳遞callback
參數,因此在“遞歸”調用中它將是undefined
並且您會收到您發布的異常。 做了
if ($.checkProgress() == false) {
$.wait(timeout, debug, callback);
// ^^^^^^^^
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.