Timing Issues With Jquery Deferred
Solution 1:
Made a big refactor and here is one final working example, with progress monitoring.
Now the important parts.
- JQuery deferreds do not execute any progress callbacks, after the resolve has been called (with one exception). In your example (without setTimeout), the deferred is immediately resolved, no chances to run progress.
- Do the hooks of all callbacks, especially the progress ones, before we trigger enything on the final Deferred. This is achieved by passing the final Deferred (now beacon) to the execution function, after we have populated it's triggers.
- I refactored the API so the func to be executed is deferred agnostic.
- This solution, uses a closure of a local (to the reduce iterator function) Deferred, inside the memo.then function, in order to continue the execution chain.
EDIT: I forgot your first question. This behavior is achieved via the means of a closure (the dfd variable in the "x" function).
The function "x" returns immediately (after triggering a notify event which now can be processed, as all the Deferreds of the execution chain have been created, and the done, fail, progress hooks of the "executePromiseQueueSync" have been hooked).
Also the function of the setTimeout "closes" the dfd in a closure, so it can access the variable despite that the "x" has returned. The "then" call continues by creating the next deferred that is linked to the first one.
After the JS VM yields (it has not other things to do), the setTimeout triggers it's associated function, that (by the means of closure) have access to the "closed" dfd variable. The Deferred is resolved and the chain can continue.
EDIT2: Here is a refactored version that adds support for long executing, deferred supported functions, where they notify their caller for their progress.
EDIT3: Here is another version, without underscore binding and with a jq-ui progressbar example.
By the way this is very good idea for complex app initialization routines.
Source (of the first version)
functionexecutePromiseQueueSync(queue, beacon){
var seed = $.Deferred(),
le = queue.length,
last;
beacon.notify(0);
last = _.reduce(queue, function(memo, ent, ind){
var df = $.Deferred();
df.then(function(){
console.log("DBG proggie");
beacon.notify((ind+1)/le*100);
});
console.log("DBG hook funk "+ind);
memo.then(function(){
console.log("DBG exec func "+ind);
ent.funct.apply(null, ent.argmnt);
df.resolve();
});
return df.promise();
}, seed.promise());
last.then(function(){
beacon.resolve(100)
});
seed.resolve(); // triggerreturn beacon.promise();
}
functionx(){
// do stuffconsole.log("blah");
}
var promisesQueue = [],
beacon = $.Deferred();
promisesQueue.push({funct: x, argmnt:[]});
promisesQueue.push({funct: x, argmnt:[]});
promisesQueue.push({funct: x, argmnt:[]});
functionmonTheProg(pct)
{
console.log('progress '+pct);
}
// first hook, then exec
beacon.then(function(){
console.log('success');
}, function(){
console.log('failure');
}, monTheProg);
// do the danceexecutePromiseQueueSync(promisesQueue, beacon)
Post a Comment for "Timing Issues With Jquery Deferred"