Pressidian
花园入口
笔记
项目
关于
实验室
GitHub
花园入口
笔记
项目
关于
实验室
GitHub

KNOWLEDGE PATHS

笔记库
当前位置
笔记库/前端/项目笔记/代达罗斯/模式

procedure中的service位置

2 分钟阅读 · Note

目录树 578 篇

            • 表单最佳实践指南
            • 双层级导航结构
            • 以schema为中心的
            • 异步三态切换
            • 用neverthrow进行错误处理
            • Anatomy
            • cn
            • LoadingState&useList的组合
            • procedure中的service位置
            • scrollbar-gutter
            • TailwindCSS
            • TanStack Router 路由模式
            • useDebounce
            • useForm
            • void
          • 项目待做
          • 性能优化
          • UI设计
      • 前端技术栈
    • 笔记目录
    • CLAUDE.md
    • Vue 组件与 Render 函数

关联笔记 6

↗表单最佳实践指南同一路径↗双层级导航结构同一路径↗以schema为中心的同一路径↗异步三态切换同一路径↗用neverthrow进行错误处理同一路径↗Anatomy同一路径

有区别,但当前业务行为基本一致,主要差别是生命周期。

放在 procedure 内:

.query(async ({ input }) => {
  const service = createAnatomiesModule(db).service;
  return service.list(input);
});

每次请求都会重新创建:

  • Anatomy DAO
  • Draft DAO
  • Version DAO
  • Repository
  • Service 及其内部函数

放在模块顶层:

const anatomiesService = createAnatomiesModule(db).service;

这些对象只在模块加载时创建一次,之后所有请求复用。在 Serverless 环境中通常是“每个实例冷启动创建一次”,而不是全平台永久唯一。

当前放外面更合适,因为:

  • Service、DAO 和 Repository 都只是持有 db 的无状态闭包。
  • 没有保存当前用户、request、session 等请求级数据。
  • 没有跨请求共享的可变状态。
  • 避免每个 procedure 重复装配同一组依赖。
  • Router 内代码更聚焦于校验输入、调用 Service、处理结果。

只有以下情况才应该在请求内部创建:

  • Service 需要当前用户或 session。
  • Service 保存请求级缓存或 trace ID。
  • 每个请求需要独立事务。
  • Service 内部存在可变状态。
  • 不同请求需要注入不同实现。

当前 Anatomy Service 不属于这些情况,因此外部创建是合理的。

不过更可测试的最终形态是把 Router 本身也做成工厂:

export const createAnatomiesRouter = function (
  service: AnatomiesService,
) {
  return router({
    list: publicProcedure.query(({ input }) => service.list(input)),
  });
};

export const anatomiesRouter = createAnatomiesRouter(
  createAnatomiesModule(db).service,
);

这样生产环境复用一个无状态 Service,测试时又可以注入 mock Service。就当前 COD-292 的范围来说,现有模块顶层创建已经没问题,不必为了生命周期再迁回 procedure 内。