Browse Source
* Resolves normal objects * Resolves promises in objects * Resolves nested promises * Fails on circular objects with more than one ref to selftags/v0.10.0
Muthu Kumar
7 years ago
1 changed files with 67 additions and 0 deletions
@ -0,0 +1,67 @@ |
|||||
|
"use strict"; |
||||
|
|
||||
|
const isObject = obj => obj && typeof obj === 'object' && obj.constructor === Object; |
||||
|
|
||||
|
const makeCircular = (obj, path) => { |
||||
|
const start = (o, p, i = 1) => { |
||||
|
if (i === path.length) return o[p[0]] = obj; |
||||
|
if (p.length > 0) { |
||||
|
o[p[0]] = {}; |
||||
|
return start(o[p[0]], p.slice(1), i + 1); |
||||
|
} else return obj; |
||||
|
} |
||||
|
return start(obj, path); |
||||
|
}; |
||||
|
|
||||
|
const findPath = (obj, query) => { |
||||
|
return Object.keys(obj).reduce((acc, key) => { |
||||
|
const value = obj[key]; |
||||
|
if (value === query) return [...acc, key]; |
||||
|
if (isObject(value)) return [...acc, ...findPath(value)]; |
||||
|
else return acc; |
||||
|
}, []); |
||||
|
}; |
||||
|
|
||||
|
// Resolves array
|
||||
|
const PromiseMap = (arr, functor) => |
||||
|
Promise.all(arr.map(x => Promise.resolve(x).then(functor))); |
||||
|
|
||||
|
// Resolves objects
|
||||
|
const ResolveObject = obj => |
||||
|
Promise.all( |
||||
|
Object.keys(obj).map(key => |
||||
|
Promise.resolve(obj[key]).then(val => obj[key] = val)) |
||||
|
) |
||||
|
.then(_ => obj); |
||||
|
|
||||
|
// Resolves recrusive deep objects
|
||||
|
const PromiseObject = parent => { |
||||
|
const ResolveDeepObject = object => |
||||
|
Promise |
||||
|
.resolve(object) |
||||
|
.then(obj => { |
||||
|
if (Array.isArray(obj)) { |
||||
|
return PromiseMap(obj, obj => ResolveDeepObject(obj)); |
||||
|
} else if (isObject(obj)) { |
||||
|
return ResolveObject( |
||||
|
Object |
||||
|
.keys(obj) |
||||
|
.reduce((acc, key) => |
||||
|
(obj[key] === parent) ? { |
||||
|
...acc, |
||||
|
[key]: '[[ SELF ]]', |
||||
|
} : { |
||||
|
...acc, |
||||
|
[key]: ResolveDeepObject(obj[key]), |
||||
|
}, {})); |
||||
|
} |
||||
|
return obj; |
||||
|
}); |
||||
|
return ResolveDeepObject(parent) |
||||
|
.then(obj => { |
||||
|
const path = findPath(obj, '[[ SELF ]]'); |
||||
|
return path.length > 0 ? makeCircular(obj, path) : obj; |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
module.exports = PromiseObject; |
Loading…
Reference in new issue