treeverse
Walk any kind of tree structure depth- or breadth-first. Supports promises
and advanced map-reduce operations with a very small API.
Treeverse does not care what kind of tree it is, it will traverse it for
you just fine. It does the right thing with functions that return
Promises, and returns a non-Promise value if your functions don't return
Promises.
Rather than imposing a specific structure, like requiring you to have child
nodes stored in a children
array, it calls the supplied getChildren()
function, so the children can be anywhere (or not even exist yet!) This
makes it suitable for creating an optimized tree from a set of dependency
manifests, for example.
USAGE
const {depth, breadth} = require('treeverse')
depth({
tree: rootNode,
visit (node) {
},
leave (node, children) {
},
getChildren (node, nodeResult) {
},
filter (node) {
},
})
breadth({
tree: rootNode,
visit (node) {
},
getChildren (node, nodeResult) {
},
filter (node) {
},
})
API
Both functions take a single options object as an argument, and return
either the result value, or a Promise to the result value if the
methods in the options argument ever return a Promise.
treeverse.breadth
- Perform a breadth-first traversal. That is, walk
across node siblings before traversing node children.treeverse.depth
- Perform a depth-first traversal. That is, walk
down into child nodes before traversing siblings.
OPTIONS
All function options can return a Promise or actual value.
The return value is the result of the top level visit function if no leave
function is provided, or leave. If any method along the way returns a
promise, then the top level function will return a promise which resolves
to the result of visiting (and leaving) the top node in the tree.
tree
- The initial node where the traversal begins.visit(node)
- Function to call upon visiting a node.leave(node, children)
- (Depth only) Function to call upon leaving a
node, once all of its children have been visited, and potentially left.
children
is an array of child node visit results. If the graph is
cyclic, then some children may have been visited but not left.getChildren(node, nodeResult)
- Get an array of child nodes to process.filter
- Filter out child nodes from the traversal. Note that this
filters the entire branch of the tree, not just that one node. That is,
children of filtered nodes are not traversed either.
STACK DEPTH WARNING
When a leave
method is specified, then recursion is used, because
maintaining state otherwise is challenging. This means that using leave
with a synchronous depth first traversal of very deeply nested trees will
result in stack overflow errors.
To avoid this, either make one or more of the functions async, or do all of
the work in the visit
method.
Breadth-first traversal always uses a loop, and is stack-safe.
It is possible to implement depth first traversal with a leave method
using a loop rather than recursion, but maintaining the leave(node, [children])
API surface would be challenging, and is not implemented at
this time.