【问题标题】:"message": "Cannot read properties of undefined (reading 'asyncIterator')", in Apollo Studio"message": "Cannot read properties of undefined (reading 'asyncIterator')", 在 Apollo Studio
【发布时间】:2022-03-29 22:36:19
【问题描述】:

我在 Apollo Studio 中提交订阅时收到以下响应,但我正在迷失调试!我似乎找不到问题。

通常在执行server.installSubscriptionHandlers() 时一切都会正常工作,但现在在 Apollo 版本 3 中,根据文档,必须以不同的方式完成。 在这里阅读更多:https://www.apollographql.com/docs/apollo-server/data/subscriptions/

我的包裹:

"graphql-subscriptions": "^2.0.0",
"graphql-tools": "^4.0.8",
"subscriptions-transport-ws": "^0.11.0",
"apollo-server-express": "^3.5.0",
"express": "^4.17.2",

ApolloStudio 中的响应:

{
  "errors": [
    {
      "message": "Cannot read properties of undefined (reading 'asyncIterator')",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "newTodo"
      ]
    }
  ]
}

我在 ApolloStudio 中输入的内容:

subscription {
  newTodo {
    description
    id
    title
  }
}

我的相关解析器代码:

const NEW_TODO = "NEW_TODO";

const resolvers: IResolvers = {
//...
Mutation: {
        addTodo: async (
            parent,
            args: null,
            { pubsub },
            info: any
        ): Promise<Todo> => {
            const newTodo: Todo = {
               id: v4(),
               title: "New Todo!",
               description: "New Todo, Wohoo" 
            }
            todos.push(newTodo);
            pubsub.publish(NEW_TODO, { newTodo });
            return todos[todos.length - 1];
        }
    },
    Subscription: {
        newTodo: {
            subscribe: (_, __, {pubsub}) => pubsub.asyncIterator(NEW_TODO),
        },
    }
}

我的 Typedef:

type Subscription {
    newTodo: Todo!
}

我的服务器:


//...

const pubsub = new PubSub();

const apolloServer = new ApolloServer({
    schema,
    context: ({req, res}): any => ({req, res, pubsub}),
    plugins: [{
        serverWillStart: async () => {
            return {
                async drainServer() {
                    subscriptionServer.close();
                }
            }
        }
    }],
});

(async function() {
    await apolloServer.start();
    apolloServer.applyMiddleware({ app, cors: true }); 
})();

const httpServer = createServer(app);
const subscriptionServer = new SubscriptionServer({
    schema,
    execute, 
    subscribe,
    onConnect() {
        console.log("SubscriptionServer ready!");
    },
}, {
    server: httpServer,
    path: "/graphql"
});

//...

【问题讨论】:

  • 我不使用graphql,但subscribe: (_, __, {pubsub}) =&gt; pubsub.asyncIterator(NEW_TODO), 无疑是你的问题,你的回调没有传递你认为的东西。
  • 好的,还是很有帮助的,谢谢@JaredSmith
  • @JaredSmith 兄弟你刚刚帮我解决了你是个天才,上帝保佑你兄弟。
  • 很高兴你解决了!

标签: typescript graphql apollo apollo-server


【解决方案1】:

正如@Jared Smith 所说,subscribe() 没有接收到pubsub 存在问题,所以我通过转到服务器代码并将const pubsub 更改为export const pubsub 并将其导入到解析器。似乎是一个不优雅的解决方案,但它现在可以完成工作!

【讨论】:

    【解决方案2】:

    我通过使用useServer在websocket服务器上设置上下文解决了这个问题,查询和变异似乎与订阅有不同的上下文,这是我的代码

    (async () => {
        const app = express();
        const httpServer = createServer(app);
        const pubsub = new PubSub();
    
        app.use(cors());
    
        const schema = makeExecutableSchema({ typeDefs, resolvers});
    
        const wsServer = new WebSocketServer({
            server: httpServer,
            path: '/graphql',
        })
    
        const serverCleanup = useServer({ 
            schema, 
            context: (ctx, msg, args) => ({ pubsub }), // <-- SOLVES IT
            }, wsServer);
    
        const apolloServer = new ApolloServer({
            schema,
            context: ({ req, res }: any) => ({req, res, pubsub}),
            plugins: [
                ApolloServerPluginDrainHttpServer({ httpServer }),
                {
                    async serverWillStart() {
                        return {
                            async drainServer(){
                                await serverCleanup.dispose();
                            },
                        };
                    }
                },
            ],
        });
        
        await apolloServer.start();
    
        apolloServer.applyMiddleware({ app, cors: false });
    
        httpServer.listen({ port: 8000 }, () => {
            console.log(
                `? Query endpoint ready at http://localhost:8000${apolloServer.graphqlPath}`
            );
            console.log(
                `? Subscription endpoint ready at ws://localhost:8000${apolloServer.graphqlPath}`
            );
        });
    })()
    

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 2021-11-10
    • 2021-11-03
    • 2021-11-08
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 2022-07-09
    • 2022-12-02
    • 2022-01-11
    相关资源
    最近更新 更多