Created
January 27, 2014 23:36
-
-
Save cpdean/8659630 to your computer and use it in GitHub Desktop.
q.js demo for merging the results of an arbitrary number of promises generated by an initial promise.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @cpdean | |
// demonstrates how to have one promise kick off | |
// an additional arbitrary number of promises, and | |
// then merge their results down again after | |
// all the promises are complete. | |
var Q = require('q'); // "q": "~1.0.0" | |
// initial query that generates seed data for more work to be done | |
function fakeQuery(){ | |
var deferred = Q.defer(); | |
setTimeout(function(){ | |
console.log("first query complete"); | |
deferred.resolve([{id: 1}, {id: 2}, {id: 3}]); | |
}, 1e3); | |
return deferred.promise; | |
} | |
// second query | |
function deferredPropertyLookup(x) { | |
var deferred = Q.defer(); | |
setTimeout(function(){ | |
console.log("next query complete on " + x); | |
deferred.resolve(x); | |
}, 1e3); | |
return deferred.promise; | |
} | |
fakeQuery().then(function(results){ | |
// `results` could be an arbitrary number of things | |
// to do more work on | |
// then concurrently run the lookup function with its | |
// post processing step in then() | |
var with_properties = results.map(function(e){ | |
return deferredPropertyLookup(e.id).then(function(found){ | |
return {id: e.id, prop: found}; | |
}); | |
}); | |
return Q.all(with_properties).done(function(a){ | |
// print the results when the lookups and processing are done | |
console.log(a); | |
}); | |
}); |
Great example! One that actually works when copy/pasted into a file.
There are some people who think including a line like
var Q = require('q');
is too much distraction.
Here is a snippet I use when I need to run an arbitrary number of promises one at a time sequentially. This is handy if you are making a lot of API calls and don't want to exceed rate or concurrent request limits.
function runPromiseSequence(items) {
return items.map(function(item) {
// Have to wrap this in a function to generate a promise for each item
return function() {
// return a value or promise
return item.doSomethingAsync();
};
}).reduce(Q.when, Q());
}
The function will return a promise chain for each item in the array, like ...then(function(item[0] { ... }).then(function(item[1]) { ... })
etc and you can add to the end of the chain to do something after all the other promises are resolved sequentially.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I lost hours trying to reproduce what they already have!
I wanted to execute promises and non promises in the order and get all the values in the end, so I did this snippet:
http://jsbin.com/vumakumuqu/5/edit
When in the end I could do pratically the same with:
To get the same result, I will just use the same wrapper to return objects instead of values only, and merge then all into one, end of story!
Documentation needs refactoring, also some graphical information, promise system and recursion are better visualized in images I think.
Cheers!