Feathers.js 的 Services 与 Hooks 设计
· 阅读需 2 分钟
真正把 Feathers.js 用起来之后,很快会遇到一个问题: service 到底该写多厚,hook 到底该放多少逻辑?这个边界如果不早点想清楚,项目照样会越写越乱。
我现在比较认可的一条原则是:
- service 负责核心业务动作
- hook 负责横切逻辑和流程编排
这个区分不花哨,但很耐用。
service 最好只关心业务动作本身
拿文章发布举例,service 真正该关心的是:
- 文章数据怎么写入
- 状态如何变更
- 是否需要同步标签或分类关系
而不是在 service 内部再混着做 token 校验、参数修剪、权限判断、返回值脱敏这些事。
class PostsService {
async create(data, params) {
return this.model.create({
...data,
authorId: params.user.id,
status: 'draft',
});
}
}
这样 service 看起来很薄,但它表达的是最核心的业务动作。
hook 适合承接哪些逻辑
我一般把 hook 用在四类地方:
- 身份认证
- 参数校验
- 数据注入
- 结果清理
比如创建文章时:
module.exports = {
before: {
create: [
authenticate('jwt'),
validatePostPayload(),
attachTraceId(),
],
},
after: {
create: [
stripInternalFields(),
],
},
};
这样一来,service 本身更聚焦,接口入口也更统一。
不要把 hook 写成第二个业务层
这是很多人一开始最容易踩的坑。因为 hook 用起来顺手,就什么都往里面塞。最后变成:
- 业务分支散在多个 hook
- 顺序一变,行为就变
- 新人很难看懂一条请求到底经过了什么
所以 hook 最好只做“横切”和“轻编排”,而不是承担复杂业务决策。
service 与 hook 的协作方式
一条比较稳的链路通常长这样:
- before hook 做认证和校验
- service 执行核心业务
- after hook 做输出修剪和审计日志
如果中间还需要跨多个 service 协作,我更建议在 service 层再抽一个业务方法,而不是让 hook 串起一整条复杂流程。
小结
Feathers.js 写得舒服不舒服,关键不在框架,而在 service 和 hook 的职责有没有收清楚。service 要短,但不能空;hook 要有用,但不能滥。这两个边界一旦站稳,整个 Node.js 项目的可维护性会明显好很多。
