Last active
December 30, 2015 06:04
-
-
Save RSNara/900ad5567c2a66f7c7d4 to your computer and use it in GitHub Desktop.
Promise.tree
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
/** | |
* A Tree is an Object that may contain other Trees, Objects, Promises, | |
* or primitives. By definition, it contains no cycles. | |
* @typedef [Object] Tree | |
*/ | |
/** | |
* @function tree | |
* @memberof Promise | |
* @param [Tree] tree | |
* @returns [Promise] - A Tree with all promises resolved. | |
* | |
* @description | |
* Works like $q.all, but for arbitrarily nested objects. | |
* | |
* @example | |
* ```javascript | |
* const tree = { | |
* one: Promise.resolve(1), | |
* two: { | |
* three: 'three', | |
* four: Promise.resolve(4), | |
* }, | |
* five: 5, | |
* }; | |
* | |
* Promise.tree(tree).then((result) => { | |
* assert.deepEqual(result, { | |
* one: 1, | |
* two: { | |
* three: 'three', | |
* four: 4, | |
* }, | |
* five: 5, | |
* }); | |
* }); | |
* ``` | |
*/ | |
const isObject = (x) => Object(x) === x; | |
const isTree = (x) => isObject(x) && ! (typeof x.then === 'function'); | |
const transform = (x) => isTree(x) ? Promise.tree(x) : x; | |
const keys = (x) => Object.keys(x); | |
const objectKeyReduce = (fn, init, x) => keys(x).reduce(fn, init); | |
const merge = (...args) => Object.assign({}, ...args); | |
function zip(names) { | |
return (values) => names.reduce( | |
(map, name, index) => merge(map, { | |
[name]: values[index], | |
}), {} | |
); | |
} | |
Promise.tree = (tree) => ( | |
Promise.all( | |
objectKeyReduce( | |
(promises, key) => ( | |
[...promises, transform(tree[key])] | |
), [], tree | |
) | |
).then( | |
zip(keys(tree)) | |
) | |
); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment