【发布时间】:2021-08-08 12:56:57
【问题描述】:
请耐心等待,因为这需要一些出发点。
出于问题/讨论的目的,考虑一下这个平凡的价值树。
const valuetree = [{
item: 1,
value: 100,
},
{
item: 2,
value: [{
item: 3,
value: [{
item: 4,
value: 200
},
{
item: 5,
value: 200
},
{
item: 6,
value: 200
},
]
}]
},
];
现在,如果我们想编写一个递归函数来将所有值相加,那么这本身就相当简单。像这样:
function sumTree(leaf) {
let total = 0;
if (Array.isArray(leaf)) {
leaf.forEach(subLeaf => {
total += sumTree(subLeaf);
});
} else {
if (Array.isArray(leaf.value)) {
total += sumTree(leaf.value);
} else {
total += Number(leaf.value);
}
}
return total;
}
现在假设我们想使用 Promise 来实现相同的目标?
这就是我最终的结果......
async function sumTreeAsync(leaf) {
let promises = [];
if (Array.isArray(leaf)) {
leaf.forEach(async subLeaf => {
promises.push(sumTreeAsync(subLeaf));
});
} else {
if (Array.isArray(leaf.value)) {
promises.push(sumTreeAsync(leaf.value));
} else {
promises.push(leaf.value);
}
}
return promises;
}
所以返回的内容是这样的
[ Promise { [ 100 ] }, Promise { [ [Promise] ] } ]
这是有道理的,一个由 2 个顶级项组成的数组,一个字面值的承诺,以及一个返回嵌套的承诺数组的承诺。
所以现在像 Promise.all 这样的函数只处理一组平面的 Promise,我必须递归嵌套的 Promise 才能得到相同的结果。所以现在我必须递归这棵树两次,这闻起来很糟糕。
所以也许我需要从子叶是数组的 2 种情况中返回已解决的承诺?
这样做是否值得,或者递归应该是同步的?
【问题讨论】:
-
你期望什么做作为返回值?你的目标是什么?你可能想要一个迭代器?不知道你为什么要承诺。
-
一个函数通常不应该返回一个promise数组,而只是调用
Promise.all本身并返回一个数组的promise。 -
我想要做的是以最省时的方式遍历树并将所有值加起来为一个总量。因为它显然可以在每个级别同时处理,所以我想使用 async/await。但是当你将递归和承诺混为一谈时,事情就变得有点复杂了。
-
@ScottSauyet 是的,这意味着一般性的批评,以及指向有关异步循环的规范问题的指针。当然,具体来说,如果只是将 promise 推送到数组中,这个函数首先不应该是
async,并且应该简化为return Promise.all(leaf.map(sumTreeAsync))。但是 trincot 的问题仍然存在,在我们得到 OP 的回复之前,我不会写答案。
标签: javascript recursion promise tree es6-promise