【发布时间】:2019-01-08 00:11:36
【问题描述】:
我想使用嵌套的Promise's 创建一个树形结构。
当 Promise 在树结构中解析时,它将从内到外解析(子节点然后父节点)。我需要让从父到子的兄弟承诺的执行可以并行运行。
我想出了一种方法来延迟执行,方法是解决一个闭包,该闭包将延迟已解决的承诺的操作,并从上到下递归调用每个函数。这是一个相当优雅的解决方案,但是,我可以使用任何其他约定或功能对象来执行该操作。我真的不想解决树中每个节点的闭包问题,因为这会增加教人们使用它的复杂性。
我宁愿不使用 async/await,而是坚持使用 Promise 或其他函数式 JS 对象。
第一个示例将显示嵌套 Promise 的解析顺序。
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>
干杯
【问题讨论】:
-
在您的第一个示例中,您没有显示执行顺序,而是显示已解决的顺序。 IOW:做一个 console.log 并解析你会更好地看到它的值。
-
@Keith 对不起,我说错了。我只关心承诺的解决顺序。它们用于异步节点树中,例如父节点可以从服务器下载html模板,子节点可以向html模板添加功能,因此父节点必须在子节点之前执行。第一个例子表明,孩子首先被执行。
-
我对这个问题有点坚持,因为“返回闭包”和“解决闭包”并不正确。闭包不是可以返回或解决的东西。
-
@Roamer-1888 感谢您指出差异。我已将其更正以解决,因为您无法从承诺中返回值。闭包只是表达功能的一种方式。它可以从 Promise 中解析,然后从
then函数中调用。例如。Promise.resolve(() => 'resolved value').then(fn => console.log(fn()))
标签: javascript promise functional-programming tree