Node.js:将字符串转为HTTP路由基数树(替换root为nodes)
替换HTTP路由基数树的root属性为nodes属性的实现方案
我正在为HTTP路由实现类似基数树的结构,现有TypeScript代码通过Tree类的root属性实现路由插入逻辑,能生成包含root的树形结构,但需要把Tree类中的root变量替换为nodes属性,得到指定的目标结构。尝试多次后代码混乱,求正确实现。
现有代码
interface Node { nodes?: Record<string, Node> methods?: Record<string, () => unknown> } class Tree { root: Node constructor() { this.root = {} } insert(path: string, method: string, handler: () => unknown): void { let node = this.root path.split('/').forEach((path: string): void => { path = path === '' ? '/' : path node.nodes = node.nodes ?? {} const child = node.nodes[path] ?? {} node.nodes[path] = child node = child }) node.methods = node.methods ?? {} if (!node.methods[method]) { node.methods[method] = handler } } } const tree = new Tree() tree.insert('/users', 'GET', (): string => { return 'users get handler' }) tree.insert('/posts', 'GET', (): string => { return 'posts get handler' }) tree.insert('/profile', 'GET', (): string => { return 'profile get handler' }) tree.insert('/profile/posts', 'GET', (): string => { return 'profile posts get handler' }) tree.insert('/profile/friends', 'GET', (): string => { return 'profile friends get handler' }) console.log( JSON.stringify(tree), )
当前生成结构
{ "root": { "nodes": { "/": { "nodes": { "users": { "methods": { "GET": "users get handler" } }, "posts": { "methods": { "GET": "posts get handler" } }, "profile": { "methods": { "GET": "profile get handler" }, "nodes": { "posts": { "methods": { "GET": "profile posts get handler" } }, "friends": { "methods": { "GET": "profile friends get handler" } } } } } } } } }
目标结构要求
目标Tree类定义
class Tree { nodes: Record<string, Node> }
目标树形结构
{ "nodes": { "/": { "nodes": { "users": { "methods": { "GET": "users get handler" } }, "posts": { "methods": { "GET": "posts get handler" } }, "profile": { "methods": { "GET": "profile get handler" }, "nodes": { "posts": { "methods": { "GET": "profile posts get handler" } }, "friends": { "methods": { "GET": "profile friends get handler" } } } } } } } }
正确实现代码
interface Node { nodes?: Record<string, Node> methods?: Record<string, () => unknown> } class Tree { nodes: Record<string, Node> constructor() { this.nodes = {} } insert(path: string, method: string, handler: () => unknown): void { // 确保路由根节点"/"存在 if (!this.nodes["/"]) { this.nodes["/"] = {} } let node = this.nodes["/"] // 分割路径并过滤开头的空字符串(对应路径的首/) const pathSegments = path.split('/').filter(segment => segment !== '') pathSegments.forEach(segment => { node.nodes = node.nodes ?? {} const childNode = node.nodes[segment] ?? {} node.nodes[segment] = childNode node = childNode }) // 挂载请求方法与处理器 node.methods = node.methods ?? {} if (!node.methods[method]) { node.methods[method] = handler } } } // 测试代码 const tree = new Tree() tree.insert('/users', 'GET', (): string => { return 'users get handler' }) tree.insert('/posts', 'GET', (): string => { return 'posts get handler' }) tree.insert('/profile', 'GET', (): string => { return 'profile get handler' }) tree.insert('/profile/posts', 'GET', (): string => { return 'profile posts get handler' }) tree.insert('/profile/friends', 'GET', (): string => { return 'profile friends get handler' }) console.log(JSON.stringify(tree))
修改说明
- 类属性替换:将原
root属性替换为nodes,类型定义为Record<string, Node>,构造函数初始化空对象 - 根节点处理:插入路由前先确保
this.nodes["/"]存在,作为所有路由的入口节点 - 路径处理优化:分割路径后过滤掉开头的空字符串(因为以
/开头的路径分割后第一个元素为空),直接从实际路径段开始遍历创建节点 - 逻辑保留:节点创建、方法挂载的核心逻辑保持原有逻辑不变,确保路由功能正常
内容的提问来源于stack exchange,提问作者iAxel
相关产品推荐
相关产品推荐

