簡體   English   中英

當等待值低得多時,為什么 Javascript 在 setTimeout 中說“回調不是函數”?

[英]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只有callbackundefined ......

乍一看,我認為你想在那里寫的是:

$.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。 然后, callbackundefined )將在內部調用中被調用。


當間隔減少時,這個問題開始出現。 這是有道理的,因為如果作業尚未完成,您只會遞歸調用$.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM