Eon*_*Eon -2 javascript jquery settimeout
我在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);
}
});
});
}
Run Code Online (Sandbox Code Playgroud)
工作的处理程序
$.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);
}
Run Code Online (Sandbox Code Playgroud)
这是我的小作业跑者的关键点代码,其他方法将调用$.totalJobs()
以设置需要执行的作业量(通常基于需要对API进行不同调用的量)在我的场景中,以及$.completedJobs()
-在API处理程序的回调中返回有效负载时调用
问题是,当我将"Waiter"设置为50ms时,我没有得到任何错误,并且该方法按预期执行.
当我将它设置为5ms,1ms,0ms等低值时,它告诉我:
"xxxxx.helpers.js:48未捕获的TypeError:回调不是函数"
任何人都有一个疯狂的理论为什么会发生这种情况?它毕竟只是一个美化setTimeout
.
(PS为了回应为什么我使用JQuery全局方法和变量存储信息,是为了让我自己更容易使用Meteor知道它被加载到一个地方 - 这是我正在开发的平台.)
编辑对我来说更好的是添加运行回调的整个方法
看起来你没有在这里传递一个回调:
$.wait = function(timeout, debug, callback) {
//code here
if ($.checkProgress() == false) {
$.wait(timeout, debug); // === $.wait(timeout, debug, undefined);
}
callback($.checkProgress()); // <-- complaining one
}, timeout);
Run Code Online (Sandbox Code Playgroud)
所以,如果$.checkProgress()
是假的,你打电话$.wait
递归仅callback
是undefined
...
乍一看,我认为你想写的是:
$.wait(timeout, debug, callback); // pass callback argument to inner call
Run Code Online (Sandbox Code Playgroud)
但显然,您不希望多次调用回调:
$.wait = function(timeout, debug, callback) {
//code here
if ($.checkProgress() == false) {
$.wait(timeout, debug, callback);
} else {
callback($.checkProgress());
}
}, timeout);
Run Code Online (Sandbox Code Playgroud)
您标记为"抱怨者"的行实际上是抱怨的原因是因为它是递归调用.$.checkProgress
如果计算结果为false,$.wait
则调用该函数(此时,callback
未定义),并继续执行直到$.checkProgress() === false
计算结果为false.然后,将在内部调用中调用callback
(即undefined
).
当间隔减少时,此问题开始出现.这是有道理的,因为$.wait
如果作业尚未完成,你只能递归调用.超时/间隔越高,第一次完成作业的机会就越大.
通过减少间隔,您到达$.wait
了在作业完成之前调用的点,并且您进入了$.checkProgress() === false
分支,在$.wait
不传递回调的情况下调用(基本上丢失了对它的引用).
当作业完成时,你试图调用callback
设置为的m undefined
.