如何在 React 中为上传和订阅设置 Apollo 客户端?

Posted

技术标签:

【中文标题】如何在 React 中为上传和订阅设置 Apollo 客户端?【英文标题】:How can I setup an Apollo client in React for both upload and subscriptions? 【发布时间】:2019-01-05 19:43:40 【问题描述】:

我想使用 React 设置一个 graphql 客户端,用于上传文件和处理来自 graphql 服务器的订阅。 文件上传和其他查询运行良好。问题在于订阅。我在浏览器控制台中收到以下错误: WebSocket connection to 'ws://localhost:3001/subscriptions' failed: Connection closed before receiving a handshake response

我使用apollo-upload-client 进行文件上传,使用apollo-link-ws 进行订阅。

我可以看到subscriptions-transport-ws 建议使用createNetworkInterfaceaddGraphQLSubscriptions,但这种方法与仅支持createUploadLinkapollo-upload-client 不兼容。

我被困住了。请帮忙。

我这样设置我的客户端:

import React from 'react';
import ApolloClient from 'apollo-client';
import  ApolloProvider  from 'react-apollo';
import  createUploadLink  from 'apollo-upload-client';
import  InMemoryCache  from 'apollo-cache-inmemory';
import  ApolloLink, Observable, split  from 'apollo-link';
import  WebSocketLink  from 'apollo-link-ws';
import  getMainDefinition  from 'apollo-utilities';


const cache = new InMemoryCache();

const request = async (operation) => 
    const token = localStorage.getItem('token');
    operation.setContext(
        headers: 
            authorization: token ? `Bearer $token` : '',
        ,
    );
;

const httpLink = createUploadLink( uri: 'http://localhost:3001/graphql' );

// Create a WebSocket link:
const wsLink = new WebSocketLink(
    uri: 'ws://localhost:3001/subscriptions',
    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
const link = split(
    // split based on operation type
    ( query ) => 
        const  kind, operation  = getMainDefinition(query);
        return kind === 'OperationDefinition' && operation === 'subscription';
    ,
    wsLink,
    httpLink,
);


const requestLink = new ApolloLink((operation, forward) =>
    new Observable((observer) => 
        let handle;
        Promise.resolve(operation)
            .then(oper => request(oper))
            .then(() => 
                handle = forward(operation).subscribe(
                    next: observer.next.bind(observer),
                    error: observer.error.bind(observer),
                    complete: observer.complete.bind(observer),
                );
            )
            .catch(observer.error.bind(observer));

        return () => 
            if (handle) handle.unsubscribe();
        ;
    ));

const apolloClient = new ApolloClient(
    link: ApolloLink.from([
        requestLink,
        link,
    ]),
    cache,
);

export const withApolloClient = App => (
    <ApolloProvider client=apolloClient>
        <App client=apolloClient />
    </ApolloProvider>
);

export default apolloClient;

【问题讨论】:

您使用哪种服务器实现来支持 GraphQL 订阅? 你的后端是nodejs还是其他的? 服务器是用nodejs使用模块apollo-server-expressapollo-upload-serverexpressgraphqlsubscriptions-transport-ws制作的 我试图思考问题所在。但它很难猜测和回答。你有机会分享源代码吗?我想尝试一下。我可能会得到一些更好的想法和解决方案。 你弄明白了吗? @FedericoBellucci 【参考方案1】:

我正在使用类似的配置,但不是从 apollo-link-ws 导入 WebSocketLink,而是从 @apollo/client 导入它。

通过该设置,我可以同时进行订阅和上传。

import WebSocketLink from "@apollo/client/link/ws";

【讨论】:

【参考方案2】:

我建议像this 一样使用graphql-server-express

【讨论】:

以上是关于如何在 React 中为上传和订阅设置 Apollo 客户端?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Visual Studio Code 中为 React Native 设置调试?

当您不知道内容的大小时,如何在 react native 中为高度设置动画?

如何在 React Native 中为 useRef 钩子设置 Typescript 类型?

如何在 React Native 中为 TextInput 设置 lineHeight 样式?

如何在React Native中为SVG坐标设置动画?

如何在 react-router 中为 Link 或 IndexLink 的包装元素设置 activeClassName?