首页 > 解决方案 > 从父级到子级连续执行 Promise 树

问题描述

我想使用嵌套Promise的创建树结构。

当 promise 在树结构中解析时,它将从内到外解析(子项然后父项)。我需要让从父到子的兄弟承诺的执行可以并行运行。

我想出了一种方法来延迟执行,方法是解决一个闭包,该闭包将延迟已解决的承诺的动作,并从上到下递归调用每个函数。这是一个相当优雅的解决方案,但是,我可以使用任何其他约定或功能对象来执行该操作。我真的不想解决树中每个节点的闭包问题,因为它会增加教人们使用它的复杂性。

我宁愿不使用 async/await 而是坚持使用Promise's 或另一个 Functional JS 对象。

第一个示例将显示嵌套 Promises 的解析顺序。

let order = 0
const promiseTree = (name, children) => 
  Promise.all([
    new Promise(res => res(`${name} order:${order++}`)),
    children && Promise.all(children)
  ])

promiseTree('root', [
  promiseTree('child', [
    promiseTree('grandchild', [
      promiseTree('great grandchild sibling 1'),
      promiseTree('great grandchild sibling 2'),
    ])
  ])
])
.then(console.log)
<script src="https://codepen.io/synthet1c/pen/KyQQmL.js?concise=true"></script>

如果你解决了一个闭包,然后在所有承诺完成后递归调用回调,可以更正订单。

let order = 0
const promiseTree = (name, children) => 
  Promise.all([
    // --------------------- resolve a closure with the resolved value contained
    new Promise(res => res(() => `${name} order:${order++}`)),
    children && Promise.all(children)
  ])

// flatMap over the tree, if it's a function call it and return the result
const recursivelyCall = x => 
  Array.isArray(x)
    ? x.map(recursivelyCall)
    : typeof(x) === 'function' ? x() : x

promiseTree('root', [
  promiseTree('child', [
    promiseTree('grandchild', [
      promiseTree('great grandchild sibling 1'),
      promiseTree('great grandchild sibling 2'),
    ])
  ])
])
// traverse the returned values and call the functions in declared order
.then(recursivelyCall)
.then(console.log)
<script src="https://codepen.io/synthet1c/pen/KyQQmL.js?concise=true"></script>

干杯

标签: javascriptpromisefunctional-programmingtree

解决方案


第一个片段代码中的模式问题是最内层的嵌套函数(参数)首先执行;请参阅并突出显示https://astexplorer.net/#/gist/777805a289e129cd29706b54268cfcfc/5a2def5def7d8ee91c052d9733bc7a37c63a6f67https://github.com/tc39/ecma262/issues/139715处的行。

我宁愿不使用 async/await 而是坚持使用Promise's 或另一个 Functional JS 对象。

目前尚不清楚为什么该选项被排除在考虑之外。函数是 的一个async实例Promise。鉴于需求async/await是一个可行的解决方案。

console.log((async() => void 0)() instanceof Promise);

const fn = async() => {
  let order = 0
  const promiseTree = name =>
    new Promise(res => res(`${name} order:${order++}`))

  const res = [await promiseTree('root'), [
    await promiseTree('child'), [
      await promiseTree('grandchild'), [
        await promiseTree('great grandchild sibling 1')
      , await promiseTree('great grandchild sibling 2')
      ]
    ]
  ]];
  return res;
}

fn()
.then(console.log)


推荐阅读