我有一个非常复杂的JS应用程序,它通过setTimeout()在可能的情况下排队许多逻辑。这对于防止IE7 / 8中的慢速脚本警告是必要的。
我知道。我希望我也不必支持这些。
无论如何,我需要知道所有这些操作何时完成,以便我可以为用户解锁UI。
有没有办法检查JS任务队列?
答案 0 :(得分:1)
你可以计算你已经启动了多少块,并计算每个块的减少量,检查它是否为零,如果是,则运行完成逻辑。
答案 1 :(得分:1)
我认为你不能在任何浏览器中都这样做。
但是,您可以使用Promise pattern在异步操作完成时通知某人。
这是一个使用jQuery's promise implementation的简单示例,使用setTimeout
分解执行,因此不会警告用户执行时间太长的脚本:
// a factory for promises
function createPromiseFor(doWork) {
// create a deferred object
var deferred = $.Deferred();
// a function that will schedule our work;
function scheduleMoreWork() {
setTimeout(function () {
// doWork does at least some of the work, and tells us when it is done
var finished = doWork();
if (finished) {
deferred.resolve();
} else {
scheduleMoreWork();
}
}, 1);
};
// schedule the first one
scheduleMoreWork();
return deferred.promise();
}
// assuming ourFunction does its work in chunks and can resume from where it left off...
var promise = createPromiseFor(ourFunction);
promise.done(function () {
alert('done!');
});
这是一个可以暂停的函数示例,并在下次调用时恢复:
var fn = (function () {
var goal = 100,
iterationsPerInvocation = 10,
current = 0;
function invoke() {
for (var i = 0; i < iterationsPerInvocation; ++i) {
current++;
}
}
return function () {
invoke();
return current === goal;
}
})();
var promise = createPromiseFor(fn);
promise.done(function () {
alert('done!');
});
答案 2 :(得分:0)
意识到这是一个过时的线程,但是遇到了类似的需要将任务排队的问题,并且可以选择清除javascript setTimeout队列中的冗余任务,因为进程队列开始清空...
实质上包装了setTimeout和clearTimeout函数,以使用Map(名为setTimeoutQueue)来跟踪setTimeout进程队列。 (此函数包装技术并不是什么新鲜事物,正如我所见,它与自定义事件处理程序混合器一起使用,该混合器可抢占对象或类的preempt和postempt(?)方法。)核心概念是,进程从队列中弹出,活动进程可以搜索setTimeoutQueue以确定是否有多余的任务坐在队列中,如果是,则使用抢占式的clearTimeout函数来清除实际排队的进程和setTimeoutQueue跟踪的相应任务条目。
const actualSetTimeout = setTimeout;
const actualClearTimeout = clearTimeout;
setTimeoutQueue = new Map();
setTimeout = function(f, ms, ...fArgs) {
console.log(`setTimeout "${f}" - BEFORE QUEUING TASK.`);
console.log(setTimeoutQueue);
const setTimeoutHandle = actualSetTimeout(
function() {
console.log(`setTimeout "${f}" - BEFORE EXECUTION.`);
console.log(setTimeoutQueue);
const fResult = f(...fArgs);
setTimeoutQueue.delete(setTimeoutHandle);
console.log(`setTimeout "${f}" - AFTER EXECUTION.`);
console.log(setTimeoutQueue);
return fResult;
},
ms,
...fArgs
);
setTimeoutQueue.set(setTimeoutHandle, [f, ms, ...fArgs]);
console.log(`setTimeout "${f}" - AFTER QUEUING TASK.`);
console.log(setTimeoutQueue);
return setTimeoutHandle;
}
clearTimeout = function(id) {
actualClearTimeout(id);
setTimeoutQueue.delete(id);
}
console.log(setTimeoutQueue);
setTimeout((...args)=>{console.log(`5 sec timer fired with params = ${args}`)}, 5000, 555, 5555);
setTimeout((x)=>{console.log(`2 sec timer fired with first param = ${x}`)}, 2000, 222);
setTimeout(()=>{console.log(`Queued for immediate execution.`)});
console.log(setTimeoutQueue);
很明显,除了表示自定义代码注入点之外,所有的“ console.logs”都可以帮助理解执行顺序。我仅有的不确定性是抢占setTimeout和clearTimeout函数的任何副作用,但是时间和建设性的批评会告诉您...;-)