Node.js Web 框架自动路由实现 - 代码解析
这段代码实现了一个基于 Node.js 的 Web 框架的自动路由功能。它通过加载指定路径下的所有 controller 文件,自动创建路由映射。
代码解析:
- 定义 Controller 类
class Controller {
constructor(req, res, app) {
this.req = req
this.res = res
this.app = app
}
}
exports.Controller = Controller
该代码定义了一个名为 Controller 的类,用来构建控制器对象。控制器对象包含 req、res 和 app 属性,分别代表请求对象、响应对象和应用程序对象。
- 加载控制器文件
const loadController = controllerPath => {
const controllerMap = {}
const files = fs.readdirSync(controllerPath)
files.forEach(file => {
const fileState = fs.statSync(path.join(controllerPath, file))
if (fileState.isDirectory()) {
controllerMap[file] = {
isDir: true,
...loadController(path.join(controllerPath, file))
}
} else {
const controllerName = file.substr(0, file.lastIndexOf('.'))
if (controllerName) {
controllerMap[controllerName] = {
isDir: false,
value: require(path.join(controllerPath, file))
}
}
}
})
return controllerMap
}
loadController 函数用来加载指定路径下的所有 controller 文件,并返回一个控制器映射表。该函数通过 fs.readdirSync 获取指定路径下的所有文件,然后逐个判断文件类型:
- 如果是目录,则递归调用
loadController函数加载子目录下的 controller 文件; - 如果是文件,则读取文件内容,并将控制器名称和控制器对象存储在
controllerMap中。
- 创建代理对象
const errMsg = message => ({ code: 1, message, data: null })
const createProxy = (controllerMap, app) => {
return new Proxy(controllerMap, {
get(target, name) {
if (target[name]) {
if (!target[name].isDir) {
return new Proxy(target[name], {
get(target, name) {
return (req, res) => {
if (Object.getOwnPropertyNames(target.value.prototype).includes(name)) {
new target.value(req, res, app)[name]()
} else {
res.send(errMsg('method not exist'))
}
}
}
})
} else {
return createProxy(target[name], app)
}
} else {
return new Proxy({}, {
get() {
return (req, res) => {
res.send(errMsg('controller not exist'))
}
}
})
}
}
})
}
createProxy 函数创建一个代理对象,用来实现控制器的自动路由功能。代理对象会在访问控制器时自动创建路由,并根据请求方法调用对应的控制器方法。
该函数使用 Proxy 对象来代理 controllerMap。当访问 controllerMap 中的某个属性时,get 方法会被调用。该方法根据属性类型进行不同的处理:
- 如果是控制器对象,则创建一个新的代理对象,该代理对象会根据请求方法调用对应的控制器方法;
- 如果是子目录,则递归调用
createProxy函数创建子目录的代理对象; - 如果不存在,则返回一个默认的代理对象,返回错误信息。
- 导出模块
const controllerMap = loadController(path.join(__dirname, '../controller'))
module.exports = app => {
app.controller = createProxy(controllerMap, app)
return (req, res, next) => {
next()
}
}
该代码段将 createProxy 函数应用于加载的控制器映射表,并将其赋值给 app 对象的 controller 属性,用于后续路由的访问。同时,返回一个中间件函数,用于在请求处理管道中添加路由功能。
代码优化建议:
- 使用异步方式读取文件,避免阻塞主线程。
- 优化代码逻辑,减少冗余代码,提高可读性。
- 使用缓存机制,提高路由匹配效率。
- 增加错误处理机制,避免程序异常退出。
总结:
这段代码通过 Proxy 对象和递归方式实现了 Web 框架的自动路由功能,能够根据 controller 文件自动创建路由映射,简化了路由配置过程。
相关知识点:
- Node.js 核心模块
fs和path Proxy对象- 中间件
- 路由映射
- 递归
- 异步编程
- 错误处理
原文地址: https://www.cveoy.top/t/topic/nhze 著作权归作者所有。请勿转载和采集!