Problem with your code was your children value of tree object was processed by first if (vtree instanceof Promise) {. And their child never processed.
To properly process child I removed assigned assign awaited object back to vtree inside first if (Change 1) & add vtree = await fullfill(vtree) next to it (Change 2).
Use children && children.length so if children is null then it won't throw exception. (Change 3)
Test it below.
const p = v => {
return new Promise(resolve =>
setTimeout(resolve.bind(null, v), 2000)
)
}
const tree = {
element: p('foo'),
children: [
p({
element: 'bar',
children: null
}),
p({
element: 'bar2',
children: [{
element: p('foo3'),
children: null
}]
})
]
}
const fullfill = async vtree => {
if (vtree instanceof Promise) {
// Chanage 1
// assign awaited object back to vtree
vtree = await vtree;
// Chanage 2
// Call fullfill and pass vtree
vtree = await fullfill(vtree);
} else if (Array.isArray(vtree)) {
await Promise.all(vtree.map(fullfill))
} else if (typeof vtree !== 'object') {
return vtree
} else {
let {
element,
children = []
} = vtree
if (element instanceof Promise) {
element = await element
}
// Chanage 3
// use children && children.length so if children is null then it won't throw exception.
if (children && children.length) {
children = await Promise.all(children.map(fullfill));
}
return {
element,
children
}
}
return vtree
}
fullfill(tree).then(console.log)
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
Edit without await. To remove await we need to return Promise. Please review first code snippet and then check equivalent version in second snippet which return Promise instead of await.
Test it below.
const p = v => {
return new Promise(resolve =>
setTimeout(resolve.bind(null, v), 2000)
)
}
const tree = {
element: p('foo'),
children: [
p({
element: 'bar',
children: null
}),
p({
element: 'bar2',
children: [{
element: p('foo3'),
children: null
}]
})
]
}
const fullfill = async vtree => {
if (vtree instanceof Promise) {
// Chanage 1
// assign awaited object back to vtree
return vtree.then(r => fullfill(r))
//vtree = await vtree;
//vtree = await fullfill(vtree);
}
// Chanage 2
// update else if condition to if here.
else if (Array.isArray(vtree)) {
return Promise.all(vtree.map(fullfill))
} else if (typeof vtree !== 'object') {
return vtree
} else {
let {
element,
children = []
} = vtree
if (element instanceof Promise) {
// element = await element
return element.then(e => {
if (children && children.length) {
return Promise.all(children.map(fullfill)).then(c => ({
element: e,
children: c
}));
};
return {
element: e,
children: children
};
});
}
// Chanage 3
// use children && children.length so if children is null then it won't throw exception.
else if (children && children.length) {
return Promise.all(children.map(fullfill)).then(c => ({
element: element,
children: c
}));
}
}
return vtree
}
fullfill(tree).then(console.log)
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>