gpt4 book ai didi

javascript - 带着 promise 走一棵树

转载 作者:行者123 更新时间:2023-11-29 15:29:04 25 4
gpt4 key购买 nike

我有一个树结构,我想使用 Promises 遍历它,但我还没有找到适合它的代码模式。

假设我们得到了节点名称,并且将节点名称转换为节点的行为是一个异步过程(例如涉及网络访问)。还假设每个节点包含一个(可能为空)子名称列表:

function getNodeAsync(node_name) {
// returns a Promise that produces a node
}

function childrenNamesOf(node) {
// returns a list of child node names
}

我希望以具有此签名的方法结束:

function walkTree(root_name, visit_fn) {
// call visit_fn(root_node), then call walkTree() on each of the
// childrenNamesOf(root_node), returning a Promise that is fulfilled
// after the root_node and all of its children have been visited.
}

它返回一个在根节点及其所有子节点都被访问后完成的 Promise,因此它可能被调用如下:

walkTree("grandpa", function(node) { console.log("visiting " + node.name); })
.then(function(nodes) { console.log("found " + nodes.length + " nodes.")});

更新

I've create a gist that shows my first attempt .我对 walkTree() 的(有点错误的)实现是:

function walkTree(node_name, visit_fn) {
return getNodeAsync(node_name)
.then(function(node) {
visit_fn(node);
var child_names = childrenNamesOf(node);
var promises = child_names.map(function(child_name) {
walkTree(child_name, visit_fn);
});
return Promise.all(promises);
});
};

这会以正确的顺序访问节点,但最外层的 Promise 在访问所有子节点之前就解析了。 See the gist for full details .

正如@MinusFour 指出的那样,使用这种技术来展平节点列表是毫无意义的。事实上,我真的只想在所有节点都被访问后触发最终的 promise ,所以一个更现实的用例是:

walkTree("grandpa", function(node) { console.log("visiting " + node.name); })
.then(function() { console.log("finished walking the tree")});

最佳答案

好吧,处理每个节点的函数调用不是什么大问题,但收集节点值有点问题。走那棵树有点难,最好的办法是将它映射到一棵没有最终值的树。你可以使用类似的东西:

function buildTree(root_name) {
var prom = getNodeAsync(root_name);
return Promise.all([prom, prom.then(function(n){
return Promise.all(childrenNamesOf(n).map(child => buildTree(child)))
})]);
}

从那里你可以:

var flatTree = buildTree(root_name).then(flatArray);
flatTree.then(nodes => nodes.forEach(visit_fn));
flatTree.then(nodes => whateverYouWantToDoWithNodes);

要展平数组,您可以使用:

function flatArray(nodes){
if(Array.isArray(nodes) && nodes.length){
return nodes.reduce(function(n, a){
return flatArray(n).concat(flatArray(a));
});
} else {
return Array.isArray(nodes) ? nodes : [nodes];
}
}

老实说,如果你想要一个节点列表,使用树遍历器是没有意义的,你最好将它展平,然后迭代元素,但如果你愿意,你可以遍历数组树。

关于javascript - 带着 promise 走一棵树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36624131/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com