Apollo v3 GraphQL订阅报错:Must provide document 求助
解决Apollo Server v3订阅「Must provide document」错误
咱们来拆解你遇到的「Must provide document」错误——这个问题通常和订阅服务器的配置不完整或者关键依赖缺失有关。结合你提供的代码,我梳理了几个核心问题和对应的修复方案:
1. 缺失execute和subscribe函数的导入
你的代码中创建SubscriptionServer时用到了execute和subscribe参数,但没有显示导入这些函数。如果它们是undefined,订阅服务器无法正确解析请求,就会抛出「Must provide document」错误。
修复:
从@apollo/server或graphql包导入这两个函数:
import { execute, subscribe } from '@apollo/server'; // 或者从graphql包导入:import { execute, subscribe } from 'graphql';
2. 未初始化PubSub实例
代码中使用了pubsub.asyncIterator,但没有创建PubSub实例。虽然这不会直接导致「Must provide document」错误,但会导致订阅无法接收消息,也是必须修复的点。
修复:
从graphql-subscriptions导入并初始化PubSub:
import { PubSub } from 'graphql-subscriptions'; const pubsub = new PubSub();
3. 缺失HTTP服务器的创建与监听逻辑
你的代码中使用了httpServer,但没有显示创建HTTP服务器的代码。如果httpServer未正确初始化,订阅服务器无法绑定到有效的HTTP端口,会导致请求处理失败。
修复:
创建并启动HTTP服务器(以Express为例):
import http from 'http'; import express from 'express'; const app = express(); const httpServer = http.createServer(app); // ... 你的schema、resolvers、SubscriptionServer和ApolloServer配置 ... // 最后启动服务器 await server.start(); server.applyMiddleware({ app }); httpServer.listen(4000, () => { console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`); });
完整修复后的示例代码
import { gql, makeExecutableSchema, ApolloServer } from '@apollo/server'; import { execute, subscribe } from '@apollo/server'; import { SubscriptionServer } from '@apollo/server/dist/subscriptions'; import { PubSub } from 'graphql-subscriptions'; import http from 'http'; import express from 'express'; const pubsub = new PubSub(); // 模拟一个定时递增数字的任务,用于测试订阅 let num = 0; setInterval(() => { pubsub.publish('NUMINCREMENTED', { incremented: num++ }); }, 1000); const typeDefs = gql` type Subscription { incremented: Int } `; const resolvers = { Subscription: { incremented: { subscribe: () => pubsub.asyncIterator('NUMINCREMENTED'), }, }, }; (async function () { const app = express(); const httpServer = http.createServer(app); const schema = makeExecutableSchema({ typeDefs, resolvers }); const subscriptionServer = SubscriptionServer.create( { schema, execute, subscribe }, { server: httpServer, path: '/graphql' } // 确保path和ApolloServer的graphqlPath一致 ); const server = new ApolloServer({ schema, plugins: [ { async serverWillStart() { return { async drainServer() { subscriptionServer.close(); }, }; }, }, ], }); await server.start(); server.applyMiddleware({ app }); httpServer.listen(4000, () => { console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`); console.log(`🚀 Subscription server ready at ws://localhost:4000${server.graphqlPath}`); }); })();
额外注意事项
- 确保所有依赖包版本兼容:Apollo Server v3需要搭配
@apollo/server、graphql-subscriptions等包,建议查看官方文档确认版本要求。 - 在Apollo Studio中测试订阅时,确保使用正确的WebSocket协议(ws://而非http://),Studio通常会自动切换,但如果有问题可以手动指定。
内容的提问来源于stack exchange,提问作者Justice Mba
相关产品推荐
相关产品推荐

