为什么 Javascript 在等待值低得多时在 setTimeout 中说"callback is not a function"?



我用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处理程序的回调中返回有效负载时调用

问题是,当我将"Waiter"设置为50ms时,我没有得到任何错误,并且该方法按预期执行。

当我将其设置为5ms, 1ms, 0ms等低值时,它告诉我:

"xxxxx.helpers.js:48 Uncaught TypeError: callback is not a function"

谁有一个疯狂的理论为什么会发生?毕竟,它只是一个美化了的setTimeout

(注:

为了回应为什么我使用JQuery全局方法和变量来存储信息,是为了让我自己更容易使用流星,因为我知道它被加载到一个地方-这是我目前正在开发的平台。

EDIT对我来说最好添加回调运行的整个方法

看起来这里没有传递回调:

$.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。然后,callback(即undefined)将在内部调用中被调用。


当间隔减小时开始出现此问题。这是有道理的,因为只有在作业尚未完成时才递归地调用$.wait。超时时间/间隔越长,作业第一次完成的机会就越大。

通过缩短间隔,您到达了在作业完成之前调用$.wait的点,并且您进入$.checkProgress() === false分支,调用$.wait而不传递回调(实际上失去了对它的引用)。

当作业完成时,您试图调用callback m,它被设置为undefined

In

if ($.checkProgress() == false) {
    $.wait(timeout, debug);
}

你没有通过callback参数,所以在"递归"调用中,它将是undefined,你得到了你发布的异常。让它

if ($.checkProgress() == false) {
    $.wait(timeout, debug, callback);
//                         ^^^^^^^^
}

最新更新