【问题标题】:Apollo Subscriptions: Apollo Graphql is receiving updates on Playground but not on clientApollo 订阅:Apollo Graphql 在 Playground 上接收更新,但不在客户端上
【发布时间】:2020-02-05 17:17:44
【问题描述】:

我在 Apollo GraphQL 订阅上使用 react,我可以在 Apollo Playground 上接收更新,但不能在客户端上接收更新。以下是 Apollo Playground 上的回复:

Graphql 服务器位于 http://localhost:4000/,订阅位于 ws://localhost:4000/graphql。但是,它可以在操场上工作,但不能在客户端上工作。我已经以这种方式设置了 Apollo 客户端来接收来自服务器的更新:

import ApolloClient from 'apollo-boost';
import { WebSocketLink } from 'apollo-link-ws';
import { HttpLink } from 'apollo-link-http';
import { split } from 'apollo-link';
import { getMainDefinition } from 'apollo-utilities';

const httpLink = new HttpLink({
  uri: 'http://localhost:4000/graphql'
});

export const wsLink = new WebSocketLink({
  uri: `ws://localhost:4000/graphql`,
  options: {
    reconnect: false
  }
});

export const link = split(
  // split based on operation type
  ({ query }) => {
    const definition = getMainDefinition(query);
    return (
      definition.kind === 'OperationDefinition' &&
      definition.operation === 'subscription'
    );
  },
  wsLink,
  httpLink,
);



export const client = new ApolloClient({
  uri: 'http://localhost:4000/',
});

在我看来我用过useSubscriptions:

const MESSAGE_SENT_SUBSCRIPTION =  gql`subscription {
  messageSent {
    id
    message
  }
}`
const {data: newMessage, loading: newMessageLoading} = useSubscription(MESSAGE_SENT_SUBSCRIPTION, {});

在渲染时,我使用过:

{!newMessageLoading && JSON.stringify(newMessage)}

但是从客户端,它没有收到更新,但我确信它与 Graphql WebSockets 服务器连接。

服务器端:

let database = require("./src/database.js")
let schema = require("./src/schema.js");
let resolvers = require("./src/resolvers.js");
let {ApolloServer} = require("apollo-server");

// The ApolloServer constructor requires two parameters: your schema
// definition and your set of resolvers.
const server = new ApolloServer({ 
  typeDefs: schema, 
  resolvers: resolvers,
  context: {
    database
  }
});

// The `listen` method launches a web server.
server.listen().then(({ url,subscriptionsUrl ,subscriptionsPath}) => {
  console.log(`????  Server ready at ${url}`);
  console.log(`realtime here at ${subscriptionsUrl} and path ${subscriptionsPath}`)
});

我在这里做错了什么,有没有人遇到过这样的问题?

【问题讨论】:

  • 我更改了端口并收到错误wsWebSocket is closed before the connection is established.
  • @DanielRearden 客户端在端口 3000 上,graphql 端口是 4000。

标签: reactjs graphql apollo apollo-client graphql-subscriptions


【解决方案1】:

您需要将拆分链接传递给 ApolloClient 构造函数。 尝试像这样传递它(客户端):

import ApolloClient from 'apollo-boost';
import { WebSocketLink } from 'apollo-link-ws';
import { HttpLink } from 'apollo-link-http';
import { split } from 'apollo-link';
import { onError } from 'apollo-link-error';
import { getMainDefinition } from 'apollo-utilities';

const httpLink = new HttpLink({
  uri: 'http://localhost:4000/graphql'
});

export const wsLink = new WebSocketLink({
  uri: `ws://localhost:4000/subscriptions`,
  options: {
    reconnect: false
  }
});

export const link = split(
  // split based on operation type
  ({ query }) => {
    const definition = getMainDefinition(query);
    return (
      definition.kind === 'OperationDefinition' &&
      definition.operation === 'subscription'
    );
  },
  wsLink,
  httpLink,
);

export const graphqlServer = new ApolloClient({
    link: ApolloLink.from([
        onError(({
            graphQLErrors,
            networkError
        }) => {
            if (graphQLErrors) {
                graphQLErrors.map(({
                        message,
                        locations,
                        path
                    }) =>
                    console.log(
                        `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
                    )
                );
            }
            if (networkError) {
                console.log(`[Network error]: ${networkError}`);
            }
        }),
        link // YOUR LINK (NOW MATCHING YOUR CODE)
    ])
});

和服务器端:

...
const server = new ApolloServer({ 
  typeDefs: schema, 
  resolvers: resolvers,
  subscriptions: {
        path: '/subscriptions'
  },
  context: {
    database
  }
});
...

注意/subscriptions 也传递给了 ApolloClient

【讨论】:

  • 我会测试一下并告诉你。
  • 看起来你是从别处复制代码的,你能配置你的答案来匹配我的代码吗?
  • 我从我的项目中复制了同一个堆栈人。唯一改变了 - 我删除了缓存选项。
  • 'onError' 未定义,你也可以粘贴错误方法。
  • 你能用上面的方法编写代码吗?由于某些原因,您的代码对我来说不起作用。
【解决方案2】:

我必须从 apollo-client 导入 ApolloClient。这是客户端的工作配置:

import ApolloClient from 'apollo-client';
import { WebSocketLink } from 'apollo-link-ws';
import { HttpLink } from 'apollo-link-http';
import { split } from 'apollo-link';
import { onError } from 'apollo-link-error';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { getMainDefinition } from 'apollo-utilities';

export const httpLink = new HttpLink({
  uri: "http://localhost:4000/graphql", // use https for secure endpoint
});

// Create a WebSocket link:
export const wsLink = new WebSocketLink({
  uri: "ws://localhost:4000/subscriptions", // use wss for a secure endpoint
  options: {
    reconnect: true
  }
});

// using the ability to split links, you can send data to each link
// depending on what kind of operation is being sent
export const link = split(
  // split based on operation type
  ({ query }) => {
    const { kind, operation } = getMainDefinition(query);
    return kind === 'OperationDefinition' && operation === 'subscription';
  },
  wsLink,
  httpLink,
);

// Instantiate client
export const client = new ApolloClient({
  link,
  uri: "http://localhost:4000/graphql",
  cache: new InMemoryCache()
})

【讨论】:

  • 我添加了相同的代码,但订阅仍然无效
  • 你能发布一个新问题吗?我想帮助你。也许你的情况不同。
  • 我已经在这里发布了我的问题。 stackoverflow.com/questions/58659204/…
猜你喜欢
  • 2022-12-12
  • 2019-01-18
  • 2020-08-27
  • 2017-09-19
  • 2017-12-25
  • 2017-12-01
  • 2019-04-02
  • 2018-12-30
  • 2019-11-18
相关资源
最近更新 更多