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