简体   繁体   English

解决对象树中的承诺

[英]Resolve promises in object tree

  1. How do I resolve foo3我如何解决foo3

  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM