Skip to content

框架适配器

InferDI 适配器把精确的容器类型连接到框架 lifecycle。HTTP 适配器创建一个 request scope,并在框架原生位置公开它。React 适配器提供类型化 context,也可以拥有客户端创建的子 scope。

这就是适配器的全部职责。适配器只是轻薄的生命周期胶水代码:让 @inferdi/inferdi 保持零依赖的那套设计,同样把装饰器、控制器扫描、处理器参数注入和路由发现挡在内核之外。你选择接入的是框架的请求生命周期,而不是框架对依赖注入的理解。

软件包

软件包框架作用域位置仅根模式
@inferdi/fastifyFastify v5request.di支持
@inferdi/honoHono v4c.var.di不支持
@inferdi/koaKoa v3ctx.state.di不支持
@inferdi/expressExpress 5req.di不支持
@inferdi/elysiaElysia v1context.di支持
@inferdi/reactReact 19React context外部 Provider

React 使用组件 lifecycle,而不是下面的 request lifecycle。外部 Provider 永远不会释放容器;managed ScopeProvider 在 commit 后创建子 scope,并始终释放它。参见 React 适配器

通用生命周期契约

在作用域模式下,每个适配器对每个请求都会执行相同的步骤:

  1. 在请求开始时,从根容器创建作用域(createScope,默认为 root.createScope())。
  2. 在框架原生位置暴露作用域。Hono、Koa、Express 和 Elysia 会在 setup 前暴露。Fastify 只在 setup 成功后暴露 request.di,并在清理 setup 失败时短暂暴露。清理钩子仍能看到公开槽位,而错误处理器不会收到未完成的作用域。
  3. 如需在处理器运行前进行额外初始化,可使用 setupScope 设置作用域。该步骤可以是异步的。
  4. 处理请求:路由处理器和框架的错误处理器从暴露的作用域解析服务。
  5. 在框架安全的完成时机释放作用域(disposeScope,默认为 scope.dispose()),除非所有权已被转移。

共享选项

选项默认值用途
container必填暴露给应用的根容器。适配器从不释放它(Fastify 的可选 disposeRootOnClose 除外)。
createScoperoot.createScope()构建请求作用域,并在此传入声明的请求输入。可以是异步的。
setupScope在处理器运行前执行额外初始化。可以是异步的。
disposeScopescope.dispose()自定义清理。可以是同步或异步的。
autoDisposetruefalse,或返回 false 的谓词,将释放交给你的代码处理。
onDisposeError各适配器各自的接收端接收请求作用域的释放失败:Fastify 用 request.log.error,Koa 用 ctx.app.emit('error'),其余用 console.error
skipInferdiDispose(...)将某个请求标记为由应用拥有,用于流式或后台工作。

错误与所有权规则

  • setup 失败只暴露原始错误。 如果 setupScope 抛出,适配器会释放尚未构建完成的作用域并重新抛出该错误。此次清理过程中发生的清理失败会交给 onDisposeError(或接收端),绝不会被聚合进所暴露的错误中。
  • 失败的请求仍然会释放。 skipInferdiDispose 仅在响应成功时抑制清理;错误路径无论如何都会释放。Express 是例外 —— 它的回调式中间件无法观察到一个已被处理的路由错误,因此一个被跳过且失败的 Express 请求仍归应用所有。
  • autoDispose: falseskipInferdiDispose 会转移所有权。 此后由你的代码负责在正确的框架边界处释放作用域。
  • 响应产生之后发生的清理错误会被路由到接收端并吞掉。 此时响应已经发送,因此一个迟到的清理失败绝不会破坏它。

重要差异

适配器差异
FastifyonResponse 中释放;中止清理使用 onRequestAbort;可通过 disposeRootOnClose 选择启用根容器释放。
Honoawait next() 之后释放;流式辅助函数可能在流工作完成之前就返回,因此流式路由通常需要 skipInferdiDispose
Koa等待 Node 响应的 finishclose,因此普通的流式响应体不需要跳过。
Express无法从回调式中间件检测到一个已被处理的下游路由错误;一个被跳过且失败的请求仍归应用所有。
Elysia清理绑定到 onAfterResponse;如果该钩子从未触发,适配器就无法释放作用域所持有的资源。