Reputation: 777
I have a very complex JS application that queues a lot of logic to be executed when possible via setTimeout(). This is necessary to prevent slow script warnings in IE7/8.
I know. I wish I didn't have to support these either.
Anyhow, I need to know when all of these operations are finished so I can unlock the UI for the user.
Is there a way to inspect the JS task queue?
Upvotes: 1
Views: 2594
Reputation: 851
There used to be several tools for inspecting running intervals; such as:
https://chrome.google.com/webstore/detail/timeouts-and-intervals/oagmfffelnnohpbidjknmhfangoahcan
But it appears these don't work anymore. If anyone knows of a way of seeing these in Chrome (or FireFox / Edge) Developer Tools, please comment.
Upvotes: 0
Reputation: 3719
Realize this is a very dated thread, but ran into a similar need to queue tasks, with the option to clear redundant tasks in the javascript setTimeout queue, as the process queue begins emptying...
Essentially wrapped the setTimeout and clearTimeout functions to track the setTimeout process queue using a Map (named setTimeoutQueue). (This function wrapping technique isn't anything new, as I've seen it employed with custom event handler mixins, which preempt and postempt(?) methods of objects or classes.) The core concept being that as the processes pop off the queue, the active process can search setTimeoutQueue to determine if redundant tasks are sitting in the queue, and if so, use the preempted clearTimeout function to clear both the actual queued process and the corresponding task entry tracked by 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);
Obviously all the "console.logs" are there to assist in understanding the execution sequence, in addition to denoting custom code injection points. Only uncertainty I have is any side effects of preempting the setTimeout and clearTimeout functions, but time and constructive criticism will tell... ;-)
Upvotes: 1
Reputation: 633
I don't think you can do that in any browser.
But you can use the Promise pattern to notify someone when an asynchronous operation completes.
Here is an simplistic example using jQuery's promise implementation, using setTimeout
to breakup execution so the user won't be warned about scripts that take too long to execute:
// 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!');
});
And here is an example of a function which can pause itself, and resumes the next time it is called:
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!');
});
Upvotes: 1
Reputation: 8551
You could keep a count of how many chunks you've started and have each chunk decrement that count, check whether it's zero, and if so run your completion logic.
Upvotes: 1