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

为何tRPC的Context在WebSocket的每个Procedure调用时都会重置?

tRPC WebSocket连接下跨Procedure共享Context状态的问题解决

问题原因

tRPC使用wsLink时,虽然Context是在用户首次WebSocket连接时创建,但每次调用Procedure时,框架会对顶层Context对象做一次浅拷贝:

  • 直接给Context的顶层属性赋值(比如ctx.foo = 'bar'),只会修改本次调用的拷贝版Context,不会影响原始的连接级Context,下次调用时顶层属性会回到初始状态。
  • 修改Context里嵌套对象的属性(比如ctx.state.foo = 'bar')时,因为浅拷贝只复制对象引用,实际修改的是原始Context里的嵌套对象,状态就能在跨Procedure调用时保留。

解决方法

1. 用嵌套对象统一存储共享状态

初始化Context时就定义专门的嵌套状态容器,所有需要跨Procedure共享的状态都存放在这里:

// Context创建函数示例
const createContext = async ({ ws }) => {
  return {
    // 嵌套对象存储共享状态
    sharedState: {
      activeRoom: null,
      userPreferences: {}
    },
    // 顶层属性建议只放初始化后不修改的固定值
    userId: ws?.userId
  };
};

在Procedure里修改嵌套属性:

const joinRoomProcedure = publicProcedure
  .input(z.string())
  .mutation(async ({ ctx, input }) => {
    // 修改嵌套属性,状态会在同连接的其他Procedure中保留
    ctx.sharedState.activeRoom = input;
    return { joined: true };
  });

2. 禁止直接修改Context顶层属性

不要直接对Context的顶层属性做赋值操作,这类操作无法影响原始连接的Context。如果必须更新用户ID这类信息,也把它放到嵌套的状态对象里。

3. 确认WebSocket连接的生命周期

可以在createContext里添加日志,确认它只在用户首次连接时执行,而非每次调用Procedure都触发——如果每次调用都触发,说明WebSocket连接没有保持长连接,需要先排查连接配置问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:42:40