簡體   English   中英

解決對象樹中的承諾

[英]Resolve promises in object tree

  1. 我如何解決foo3

  2. 如何在沒有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>

您的代碼的問題是您的tree對象的children值首先由if (vtree instanceof Promise) { 他們的孩子從未處理過。

為了正確處理孩子,我首先將分配的分配等待的對象移回內部的vtree if (Change 1) & add vtree = await fullfill(vtree)在它旁邊(Change 2)。

使用 children && children.length 所以如果 children 為 null 則它不會拋出異常。 (變化 3)

下面測試一下。

 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>


無需await編輯 要移除await我們需要return Promise 請查看第一個代碼片段,然后檢查第二個代碼片段中return Promise而不是await等效版本。

下面測試一下。

 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>

如果您所做的只是return結果,則幾乎沒有理由使用async / await 您只能將它用於樹節點(元素+子節點)的情況,但是在那里您可以輕松地在必要的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