[英]Resolve promises in object tree
How do I resolve foo3
我如何解决
foo3
How can I resolve the object tree without async/await
with only plain Promise
(without depending on regenerator-runtime
)如何在没有
async/await
情况下仅使用普通Promise
(不依赖于regenerator-runtime
)解析对象树
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) { await 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 } if(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>
Problem with your code was your children
value of tree
object was processed by first if (vtree instanceof Promise) {
.您的代码的问题是您的
tree
对象的children
值首先由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).为了正确处理孩子,我首先将分配的分配等待的对象移回内部的
vtree
if
(Change 1) & add vtree = await fullfill(vtree)
在它旁边(Change 2)。
Use children && children.length so if children is null then it won't throw exception.使用 children && children.length 所以如果 children 为 null 则它不会抛出异常。 (Change 3)
(变化 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
.无需
await
编辑。 To remove await
we need to return Promise
.要移除
await
我们需要return Promise
。 Please review first code snippet and then check equivalent version in second snippet which return Promise
instead of await
.请查看第一个代码片段,然后检查第二个代码片段中
return Promise
而不是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>
There's hardly a reason to use async
/ await
if all you're doing is to return
the result anyway.如果您所做的只是
return
结果,则几乎没有理由使用async
/ await
。 You'd only use it for the tree node (element+children) case, but there you can easily do the transformation after the necessary Promise.all
with then
as well:您只能将它用于树节点(元素+子节点)的情况,但是在那里您可以轻松地在必要的
Promise.all
使用then
进行转换:
function treeAll(vtree) {
if (typeof vtree !== 'object' || vtree == null) {
return Promise.resolve(vtree);
} else if (vtree instanceof Promise) {
return vtree.then(treeAll);
} else if (Array.isArray(vtree)) {
return Promise.all(vtree.map(treeAll));
} else {
return Promise.all([
vtree.element,
treeAll(vtree.children)
]).then(([element, children]) => ({
element,
children
}));
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.