问题描述
我的组件正在调用订阅查询,但是由于某种原因,订阅解析器无法访问:中断的断点永远不会被激活.但是在客户端上,我得到了GraphQL订阅错误:
"订阅必须返回异步.接收:未定义"
是什么可能导致这个?
事先感谢所有信息.
订阅查询
const IM_SUBSCRIPTION_QUERY = gql` subscription getIMsViaSubscription($fromID: String!, $toID: String!){ IMAdded(fromID:$fromID, toID: $toID){ id, fromID, toID, msgText, myUserData{ id, name_first, name_last, picture_large, picture_medium, picture_thumbnail my_category } } } `;
解析器
Subscription: { IMAdded(IMThatWasAdded) { debugger; <== IS NEVER ACTIVATED subscribe: withFilter(() => SubscriptionServer.pubsub.asyncIterator(IM_ADDED_CHANNEL), (newIM, args) => { const callIsFromMsgFoldersComponent = args.toID == 0; var result; if (callIsFromMsgFoldersComponent){ result = (newIM.fromID === args.fromID || newIM.toID === args.fromID); } else { result = ((newIM.fromID === args.fromID && newIM.toID === args.toID) || (newIM.fromID === args.toID && newIM.toID === args.fromID)); } return result; })
组件
const withDataAndSubscription = graphql(GETIMS_QUERY, { options({toID}) { console.log(GETIMS_QUERY); const fromID = Meteor.userId(); return { fetchPolicy: 'cache-and-network', variables: {fromID: `${fromID}`, toID: `${toID}`} }; } , props: props => { debugger; return { loading: props.data.loading, instant_message: props.data.instant_message, subscribeToMore: props.data.subscribeToMore, subscribeToNewIMs: params => { debugger; <==IS ACTIVATED AS EXPECTED console.log(IM_SUBSCRIPTION_QUERY); <==IS OKAY const fromID = Meteor.userId(); const toID = params.toID; return props.data.subscribeToMore({ document: IM_SUBSCRIPTION_QUERY, variables: {fromID: `${fromID}`, toID: `${toID}`}, updateQuery: (previousResult, {subscriptionData}) => { if (!subscriptionData.data) { return previousResult; } const newMsg = subscriptionData.data.createIM; return update(previousResult, { instant_message: { $push: [newMsg], }, }); } }); } }; }, }) ;
推荐答案
服务器端设置和突变/订阅解析器自从我的帖子中的代码中发生了很大变化,该代码基于去年年底的Apollo libs.这是与当前Apollo Libs合作的代码,通过本文地址:https://www.itbaoku.cn/post/1938115.html
问题描述
My component is calling a subscription query, but for some reason the subscription resolver isn't being accessed: a breakpoint in it is never activated. And yet on the client I get the GraphQL subscription error:
"Subscription must return Async Iterable. Received: undefined"
What could be causing this?
Thanks in advance to all for any info.
SUBSCRIPTION QUERY
const IM_SUBSCRIPTION_QUERY = gql` subscription getIMsViaSubscription($fromID: String!, $toID: String!){ IMAdded(fromID:$fromID, toID: $toID){ id, fromID, toID, msgText, myUserData{ id, name_first, name_last, picture_large, picture_medium, picture_thumbnail my_category } } } `;
RESOLVER
Subscription: { IMAdded(IMThatWasAdded) { debugger; <== IS NEVER ACTIVATED subscribe: withFilter(() => SubscriptionServer.pubsub.asyncIterator(IM_ADDED_CHANNEL), (newIM, args) => { const callIsFromMsgFoldersComponent = args.toID == 0; var result; if (callIsFromMsgFoldersComponent){ result = (newIM.fromID === args.fromID || newIM.toID === args.fromID); } else { result = ((newIM.fromID === args.fromID && newIM.toID === args.toID) || (newIM.fromID === args.toID && newIM.toID === args.fromID)); } return result; })
COMPONENT
const withDataAndSubscription = graphql(GETIMS_QUERY, { options({toID}) { console.log(GETIMS_QUERY); const fromID = Meteor.userId(); return { fetchPolicy: 'cache-and-network', variables: {fromID: `${fromID}`, toID: `${toID}`} }; } , props: props => { debugger; return { loading: props.data.loading, instant_message: props.data.instant_message, subscribeToMore: props.data.subscribeToMore, subscribeToNewIMs: params => { debugger; <==IS ACTIVATED AS EXPECTED console.log(IM_SUBSCRIPTION_QUERY); <==IS OKAY const fromID = Meteor.userId(); const toID = params.toID; return props.data.subscribeToMore({ document: IM_SUBSCRIPTION_QUERY, variables: {fromID: `${fromID}`, toID: `${toID}`}, updateQuery: (previousResult, {subscriptionData}) => { if (!subscriptionData.data) { return previousResult; } const newMsg = subscriptionData.data.createIM; return update(previousResult, { instant_message: { $push: [newMsg], }, }); } }); } }; }, }) ;
推荐答案
Server-side setup, and mutation/subscription resolvers have changed quite a bit since the code in my post, which was based on Apollo libs from late last year. Here is code that works with current Apollo libs, via this tutorial:
SERVER SETUP
import express from 'express'; import { graphqlExpress, graphiqlExpress } from 'graphql-server-express'; import bodyParser from 'body-parser'; import cors from 'cors'; import { execute, subscribe } from 'graphql'; import { createServer } from 'http'; import { SubscriptionServer } from 'subscriptions-transport-ws'; import schema from '/imports/api/schema'; //SET UP APOLLO QUERY / MUTATIONS / PUBSUB const METEOR_PORT = 3000; const GRAPHQL_PORT = 4000; const server = express(); server.use('*', cors({ origin: 'http://localhost:${METEOR_PORT}' })); server.use('/graphql', bodyParser.json(), graphqlExpress({ schema })); server.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql', subscriptionsEndpoint: `ws://localhost:${GRAPHQL_PORT}/subscriptions` })); // Wrap the Express server const ws = createServer(server); ws.listen(GRAPHQL_PORT, () => { console.log(`GraphQL Server is now running on http://localhost:${GRAPHQL_PORT}`); // Set up the WebSocket for handling GraphQL subscriptions new SubscriptionServer({ execute, subscribe, schema }, { server: ws, path: '/subscriptions', }); }); //END OF SET UP APOLLO PUBSUB
MUTATION RESOLVER
Mutation: { createIM(root, args, context) { var associatedUsers = []; associatedUsers.push(args.fromID); associatedUsers.push(args.toID); var IDofNewIM; return Promise.resolve() .then(() => { const newIM = connectors.IMs.create(args); return newIM; }) .then(IMAdded => { // publish subscription notification pubsub.publish(IM_ADDED_CHANNEL, { IMAdded, args}); return IMAdded; }) .catch((err)=> { console.log(err); }); },
SUBSCRIPTION RESOLVER
IMAdded: { subscribe: withFilter( () => pubsub.asyncIterator(IM_ADDED_CHANNEL), (IMAdded, args) => { IMAdded = IMAdded.IMAdded; var result = ((IMAdded.fromID === args.fromID && IMAdded.toID === args.toID) || (IMAdded.fromID === args.toID && IMAdded.toID === args.fromID)); return result; } ) },