You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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))

修改说明

  1. 类属性替换:将原root属性替换为nodes,类型定义为Record<string, Node>,构造函数初始化空对象
  2. 根节点处理:插入路由前先确保this.nodes["/"]存在,作为所有路由的入口节点
  3. 路径处理优化:分割路径后过滤掉开头的空字符串(因为以/开头的路径分割后第一个元素为空),直接从实际路径段开始遍历创建节点
  4. 逻辑保留:节点创建、方法挂载的核心逻辑保持原有逻辑不变,确保路由功能正常

内容的提问来源于stack exchange,提问作者iAxel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:50:37