简体   繁体   English

当等待值低得多时,为什么 Javascript 在 setTimeout 中说“回调不是函数”?

[英]Why does Javascript say "callback is not a function" in setTimeout when the wait value is much lower?

I have written a basic job runner in javascript (utilizing some JQuery too, but that's another story for another day) and I came across this queer Issue:我已经用 javascript 编写了一个基本的工作运行程序(也使用了一些 JQuery,但这是另一天的另一个故事),我遇到了这个奇怪的问题:

The method I run to wait for all jobs to complete:我运行以等待所有作业完成的方法:

$.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);
            }
          });
      });
    }

The handlers for the job作业的处理程序

    $.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);
    }

This is the key-point code for my little job runner, other methods will call $.totalJobs() to set the amount of jobs that need to be performed (normally based on amount different calls need to be made to an API In my scenario), and $.completedJobs() - which is called when the payloads are returned in the API handler's callbacks这是我的小作业运行器的关键点代码,其他方法将调用$.totalJobs()来设置需要执行的作业数量(通常根据需要对 API 进行不同调用的数量在我的场景中) ) 和$.completedJobs() - 在 API 处理程序的回调中返回有效负载时调用

The issue is, when I set my "Waiter" to 50ms, I don't get any errors whatsoever, and the method performs as per expected.问题是,当我将“服务员”设置为 50 毫秒时,我没有收到任何错误,并且该方法按预期执行。

When I set it to low values like 5ms, 1ms, 0ms, It tells me:当我将它设置为 5ms、1ms、0ms 等低值时,它告诉我:

"xxxxx.helpers.js:48 Uncaught TypeError: callback is not a function" “xxxxx.helpers.js:48 未捕获的类型错误:回调不是函数”

Anyone have a wild-flung theory why this would occur?任何人都有一个疯狂的理论为什么会发生这种情况? it is, afterall, only a glorified setTimeout .毕竟,它只是一个美化的setTimeout

(PS In response to why I use JQuery global methods and variables to store info is to make using Meteor easier on myself knowing it's loaded into 1 place - this is the platform I am developing on at the moment.) (为了回应为什么我使用 JQuery 全局方法和变量来存储信息,是为了让我自己更轻松地使用 Meteor,因为知道它已加载到 1 个地方 - 这是我目前正在开发的平台。)

EDIT was better for me to add the whole method where the callback is run编辑对我来说更好地添加运行回调的整个方法

It looks like you're not passing a callback here:看起来你没有在这里传递回调:

$.wait = function(timeout, debug, callback) {
    //code here
    if ($.checkProgress() == false) {
        $.wait(timeout, debug); // === $.wait(timeout, debug, undefined);
    }
    callback($.checkProgress()); // <-- complaining one

}, timeout);

so if $.checkProgress() is false, you're calling $.wait recursively only callback is undefined ...所以如果$.checkProgress()是假的,你递归调用$.wait只有callbackundefined ......

At first glance, I think what you wanted to write there was:乍一看,我认为你想在那里写的是:

$.wait(timeout, debug, callback); // pass callback argument to inner call

But then obviously, you wouldn't want to invoke the callback multiple times:但显然,您不想多次调用回调:

$.wait = function(timeout, debug, callback) {
    //code here
    if ($.checkProgress() == false) {
        $.wait(timeout, debug, callback);
    } else {
        callback($.checkProgress());
    }

}, timeout);

The reason why the line you marked as "the complaining one" is in fact complaining is because it's the recursive call.您标记为“抱怨者”的行实际上是在抱怨的原因是因为它是递归调用。 $.checkProgress evaluated to false, the $.wait function is invoked (this time, callback is undefined), and that continues until $.checkProgress() === false evaluates to false. $.checkProgress评估为 false,调用$.wait函数(这次, callback未定义),并一直持续到$.checkProgress() === false评估为 false。 Then, callback (which is undefined ) will get invoked in the inner call.然后, callbackundefined )将在内部调用中被调用。


This issue started appearing when the interval was reduced down.当间隔减少时,这个问题开始出现。 That makes sense, because you're only recursively calling $.wait if the jobs hadn't been completed.这是有道理的,因为如果作业尚未完成,您只会递归调用$.wait The higher the timeout/interval, the greater the chance the jobs were completed the first time around.超时/间隔越高,第一次完成作业的机会就越大。

By reducing the interval, you arrived at a point where $.wait got invoked before the jobs had finished, and you entered the $.checkProgress() === false branch, calling $.wait without passing the callback (essentially losing a reference to it).通过减少间隔,您到达了作业完成之前调用$.wait的点,并且您进入了$.checkProgress() === false分支,调用$.wait而不传递回调(基本上丢失了一个引用到它)。

By the time the jobs had completed, you were trying to invoke callback m which was set to undefined .当作业完成时,您正在尝试调用设置为undefined callback m 。

In

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

you're not passing through the callback parameter, so in the "recursive" call it will be undefined and you're getting the exception you posted.您没有传递callback参数,因此在“递归”调用中它将是undefined并且您会收到您发布的异常。 Make it做了

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM