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

在GraphQL订阅中无法将PubSub传入Context的问题求助

订阅Resolver中Context.pubsub为undefined的问题解决

问题描述

在mongodb-express-graphql-nextjs项目中实现Subscriptions功能时,Query和Mutation的Resolver均可正常获取Context,但订阅Resolver内的Context打印为undefined,无法读取context.pubsub属性,报错信息:cannot read property 'pubsub' in 'context'。

相关Resolver代码(comment.gql.js):

export const resolvers = {
  Subscription: {
    commentAdded: {
      subscribe: (_, args, context) => {
        console.log(context) // 输出Undefined
        return context.pubsub.asyncIterator('NEW_COMMENT')  
        // 报错:无法读取context的pubsub属性
      },
    },
  },
  Query: {
      // 其他操作正常工作
  }, 
  Mutation: {
      // 其他操作正常工作
  }
}

已做配置

  • Apollo Server已创建PubSub实例,并在expressMiddleware的context中传入pubsub
  • 配置了WebSocketServer用于订阅
  • Apollo Client(Next.js)已配置GraphQLWsLink用于订阅连接
  • 通过makeExecutableSchema合并了各模块的typeDef和resolvers

解决方案

问题核心是HTTP请求的Context配置与WebSocket订阅的Context配置相互独立,你仅在expressMiddleware中传入了pubsub,但WebSocket连接的Context未做配置,导致订阅Resolver无法获取到上下文数据。

1. 配置WebSocketServer的Context

在创建并配置WebSocketServer时,需单独指定context函数,将pubsub传入:

import { WebSocketServer } from 'ws';
import { useServer } from 'graphql-ws/lib/use/ws';
import { schema } from './path/to/your/schema';
import { PubSub } from 'graphql-subscriptions';

// 全局PubSub实例(确保和expressMiddleware中使用的是同一个)
const pubsub = new PubSub();

// 绑定到现有Express服务器的WebSocket服务
const wsServer = new WebSocketServer({
  server: yourExpressHttpServer,
  path: '/graphql/subscriptions', // 订阅请求路径
});

// 配置graphql-ws服务,指定订阅专用Context
useServer(
  {
    schema,
    context: () => ({ pubsub }), // 这里传入pubsub到订阅上下文
  },
  wsServer
);

2. 核对HTTP请求的Context配置

确保expressMiddleware中的Context配置正常(这部分你已完成,可做二次验证):

import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';

const server = new ApolloServer({ schema });
await server.start();

app.use(
  '/graphql',
  express.json(),
  expressMiddleware(server, {
    context: async ({ req }) => ({ 
      pubsub, // HTTP请求上下文传入pubsub
      // 其他需要的上下文数据,如用户信息等
    }),
  })
);

3. 验证修复效果

重启服务器后重新测试订阅功能,此时订阅Resolver中的context应能正常获取到pubsub实例,调用context.pubsub.asyncIterator('NEW_COMMENT')不再报错。

关键说明

Apollo Server中,Query/Mutation对应的HTTP请求上下文由expressMiddleware的context函数生成,而订阅对应的WebSocket连接上下文由graphql-ws的useServer配置中的context函数生成,二者完全独立,必须分别配置才能保证所有Resolver都能获取到所需的上下文数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 17:12:53