与 Hasura 的 WebSocket 连接不适用于 Node.js 上的 ApolloClient v3

Posted

技术标签:

【中文标题】与 Hasura 的 WebSocket 连接不适用于 Node.js 上的 ApolloClient v3【英文标题】:WebSocket connection to Hasura does not work with ApolloClient v3 on Node.js 【发布时间】:2021-06-26 09:44:08 【问题描述】:

我创建了一个 Express/Node 服务,它使用 ApolloClient v3 订阅 Hasura 上的数据库(数据库是在 Hasura 平台上使用 Heroku 创建的)。我想通过 ApolloClient 订阅数据库更改。

我的 ApolloClient 设置如下所示(灵感来自 Split Communication Docs):

import express,  Request, Response  from "express";
import "cross-fetch/polyfill";
import ws from "ws";

import 
  ApolloClient,
  HttpLink,
  InMemoryCache,
  split,
  gql,
 from "@apollo/client/core";
import  WebSocketLink  from "@apollo/client/link/ws";
import  getMainDefinition  from "@apollo/client/utilities";

const app = express();
const port = 8080;

const httpLink = new HttpLink(
  uri: "https://my.hasura.app/v1/graphql",
  fetch,
);

const wsLink = new WebSocketLink(
  uri: "ws://my.hasura.app/v1/graphql",
  options: 
    reconnect: true,
  ,
  webSocketImpl: ws,
);

const splitLink = split(
  ( query ) => 
    const definition = getMainDefinition(query);
    return (
      definition.kind === "OperationDefinition" &&
      definition.operation === "subscription"
    );
  ,
  wsLink,
  httpLink
);

const client = new ApolloClient(
  link: splitLink,
  cache: new InMemoryCache(),
);

我已经发现将 ApolloClient 与 Node.js 结合使用:

使用 "@apollo/client/core" 导入而不是 "@apollo/client",因为这需要一个 react 依赖项(我不希望在我的后端服务上使用它) import ws from "ws"; 用于节点的 Web 套接字实现,因为这是一个浏览器功能 import "cross-fetch/polyfill"; 具有获取功能,供 ApolloClient 使用

现在应用程序运行没有错误,但我不知道为什么我的订阅不起作用。我在前端有相同的代码(有点不同,因为它是 React)并且在那里运行良好。

这是我的订阅逻辑:

const observable = client.subscribe(
  query: gql`
    subscription 
      payments() 
        amount
        id
        time
        userId
      
    
  `,
);

observable.subscribe((data: any) => 
  console.log("data", data);
);

我期待我的console.log 在数据库更改时记录一些数据 - 但它没有,并且我的 Hasura Dashboard 没有列出新的连接。 如何建立到我的数据库的 websocket 连接?

【问题讨论】:

【参考方案1】:

我发现,Node.js 客户端上的 WebSocket uri 必须以 http/https 而不是 ws/wws 开头。

有了这段代码,它现在可以工作了:

const wsLink = new WebSocketLink(
  uri: "https://my.hasura.app/v1/graphql",  // instead of "ws://my.hasura.app/v1/graphql"
  options: 
    reconnect: true,
  ,
  webSocketImpl: ws,
);

【讨论】:

以上是关于与 Hasura 的 WebSocket 连接不适用于 Node.js 上的 ApolloClient v3的主要内容,如果未能解决你的问题,请参考以下文章