Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
when: Easily fire a callback when all deferreds are complete

When, a Deferred Utility

Easily wait until all deferreds (implementing 'then') have been resolved. Accepts two arguments, an array of deferreds (must have a 'then' method accepting a callback) and a master callback, that is fired when all deferreds have been resolved. Each deferred's resolved value(s) are then passed as argument objects to the callback. This is best used with a modified version of [nano-q](nano-q, https://gist.github.com/1129049), which allows for an arbitrary number of values to be passed into the 'resolve' method. This works with the original nano-q as well.

function(
a, // array of deferreds (each implements "then")
b, // on complete callback
c // placeholder for finished deferred count
){
c = 0, // initialize complete counter
a.forEach( function(d, e, f){ // for each deferred
d.then( function(){ // attach a "then" callback
f[e] = arguments, // that puts the passed args in to an ordered array
++c == a.length // mark that this deferred is resolved
&& // if all deferreds have resolved...
b.apply({}, a) // ...fire callback, using {} as context
} )
})
}
// this version is longer (still under 140!),
// but can be used in envs without Array.forEach
function(
a, // array of deferreds (each implements "then")
b, // on complete callback
c, // placeholder
d, // placeholder
e // placeholder
){
for( // loop through all deferreds, in reverse order
c = d = a.length, // keep length for later
e = 0; // initialize complete counter
d--; // loop until zero
)
a[d] // grab deferred,
.then( function(i){ // set callback to returned fn,
return function(){ // capturing the deferred's arg position (d)
a[i] = arguments, // save callback args, preserving order
++e == c // mark that this deferred is resolved
&& // if all deferreds have resolved...
b.apply({}, a) // ...fire callback, using {} as context
}
}(d) )
}
function(a,b,c){c=0,a.forEach(function(d,e,f){d.then(function(){f[e]=arguments,++c==a.length&&b.apply({},a)})})}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 Andrew Petersen <http://kirbysayshi.github.com>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "when",
"description": "A jQuery-like 'when' (or 'join') for nano-q, (https://gist.github.com/1129049).",
"keywords": [
"deferred",
"defer",
"when",
"utility"
]
}
<!DOCTYPE html>
<title>When, for deferreds</title>
<div>Expected value: <br/><b>what when how</b><br /><b>what when how</b></div>
<div>Actual value: <b id="ret"></b></div>
<script>
// modified nano-q, allows for multiple args to resolve(): https://gist.github.com/1129049
var dfd = function(a,b){a=[];return{resolve:function(){b=arguments;while(a.length)a.shift().apply({},b);a=0},then:function(c){a?a.push(c):c.apply({},b)}}}
// this is the "official" version, but requires Array.prototype.forEach
var when = function(a,b,c){c=0,a.forEach(function(d,e,f){d.then(function(){f[e]=arguments,++c==a.length&&b.apply({},a)})})}
// this does not require Array.prototype.forEach
var whenNoES5 = function(a,b,c,d,e){for(c=d=a.length,e=0;d--;)a[d].then(function(d){return function(){a[d]=arguments,++e==c&&b.apply({},a)}}(d))}
var a = dfd(), b = dfd(), c = dfd()
whenNoES5( [a, b, c], function(a, b, c){
document.getElementById( "ret" ).innerHTML +=
'<br />' + a[1] + b[1] + c[1]
});
when( [a, b, c], function(a, b, c){
document.getElementById( "ret" ).innerHTML +=
'<br />' + a[1] + b[1] + c[1]
});
a.resolve( new Error(), 'what ' )
b.resolve( null, 'when ' )
c.resolve( null, 'how' )
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.