graphql订阅在vscode+node中失败主因是websocket未启用:apollo server v4+需手动集成subscriptions-transport-ws或改用@graphql-yoga/node;后者开箱支持同端口http/ws自动协商,推荐本地调试;务必验证upgrade头、ws连接状态及事件名与pubsub实例一致性。

GraphQL 订阅在 VSCode + Node 环境里跑不起来,大概率不是代码写错了,而是 WebSocket 连接根本没建立成功 —— 本地开发时默认 HTTP 服务不支持 subscriptions,必须显式启用 WebSocket 传输层。
VSCode 调试时 Apollo Server 不响应 subscription 请求
现象:在 GraphQL Playground 或 Apollo Client 中执行 subscription,连接卡住、无响应、控制台报 WebSocket connection to 'ws://localhost:4000/graphql' failed。
根本原因:Apollo Server 默认只暴露 HTTP endpoint(/graphql),而订阅必须走 WebSocket endpoint(如 ws://localhost:4000/graphql),但新版 Apollo Server(v4+)已移除内置 WebSocket 服务器,需手动集成 subscriptions-transport-ws 或改用更现代的 @graphql-yoga/node。
- 若用
apollo-server-expressv4+,必须额外引入subscriptions-transport-ws并手动启动SubscriptionServer,且 Express 实例需监听http.Server(不能只用app.listen()) - 若用
@graphql-yoga/node,它开箱支持 WebSocket,无需额外配置传输层,createServer()返回的实例自带start()和stop(),更适合 VSCode 调试场景 - VSCode 的
launch.json必须用attach模式或确保node --inspect启动,否则断点可能不生效,但不影响 WebSocket 连接本身
GraphQL Yoga 比 Apollo Server 更适合本地调试订阅
Yoga 的设计目标就是“零配置实时能力”,尤其对 VSCode 开发友好:它把 HTTP + WebSocket 封装在同一端口、同一路径(/graphql),客户端无需区分 http:// 和 ws://,自动协商协议。
实操建议:
使用一条命令部署ProbeChain Rydberg测试网代理节点。自动注册为Agent(NodeType=1),免gas,支持macOS/Linux/Windows。触发词:/r
- 安装:
npm install @graphql-yoga/node(别再用已归档的subscriptions-transport-ws) - 启动方式要改:用
createServer({ schema, port: 4000 }),而不是 Express + ApolloServer 组合 - PubSub 实例直接传入
context即可,Yoga 内置createPubSub(),比手写new PubSub()更轻量 - VSCode 调试时,在
launch.json中设"runtimeArgs": ["--inspect-brk"],断点能稳停在subscribe解析器里
订阅 resolver 里 asyncIterator 报错 “Cannot read property 'next' of undefined”
典型错误:在 resolver 的 subscribe 字段返回 pubsub.asyncIterator('EVENT_NAME'),但运行时报错,说明事件名不匹配或 pubsub 未正确注入上下文。
检查点:
-
pubsub.publish('EVENT_NAME', payload)中的'EVENT_NAME'必须和asyncIterator('EVENT_NAME')完全一致(大小写、空格、引号) -
pubsub实例必须通过context传入 resolver,不能在模块顶层 new 一个然后直接引用 —— Yoga/Apollo 的 context 是每次请求新建的 - 如果用 TypeScript,确保
context类型定义里包含pubsub: ReturnType<typeof createpubsub></typeof>,否则类型推导会丢失asyncIterator方法 - mutation 中调用
publish时,务必 await 或 return Promise,否则事件可能在 resolver 执行完前就丢了
VSCode 中验证订阅是否真正生效
不要只信 Playground 界面显示的 “Connected”,要看底层连接状态和数据流。
实操方法:
- 在 VSCode 终端中用
curl -i http://localhost:4000/graphql看响应头是否有Upgrade: websocket(这是 Yoga 自动协商的标志) - 打开浏览器开发者工具 → Network → Filter
ws,刷新 Playground 页面,应看到一条graphqlWebSocket 连接,状态为101 Switching Protocols - 在 resolver 的
subscribe函数里加console.log('subscribed to EVENT_NAME'),触发 mutation 后,看 VSCode Debug Console 是否输出日志 - 如果用 Apollo Client,检查
useSubscription的onError回调是否被调用 —— 常见错误是error: "Cannot return null for non-nullable field Subscription.newLink",说明resolve函数没返回 payload 字段
真正难的不是写订阅逻辑,而是确认 WebSocket 握手成功、事件名对得上、context 里 pubsub 是同一个实例 —— 这三处任一出错,订阅就静默失败,连错误都不抛。










