node.js - 与 Hasura 的 WebSocket 连接不适用于 Node.js 上的 ApolloClient v3
问题描述
我创建了一个 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"
import 而不是"@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 连接?
解决方案
我发现,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,
});
推荐阅读
- python - 在 for 循环中自动更改索引
- java - 为什么我的 .isEmpty 在此代码中不起作用?
- flutter - Flutter 选项卡中的选择性 FloatingActionButton 可见性
- python - 如何获取 Timer 中使用的函数的输出
- html - 机身右侧的空间用于放置小型设备
- join - 使用 _PARTITIONDATE 左连接
- javascript - 带有 and 的内联代码不起作用,但使用常规 if 有效
- python - PyZMQ req socket - 挂在 context.term()
- bison - Yacc 代码同时读取 IF 和 ELSE 语句
- regex - 如果正则表达式和字符串都是变量,如何在 perl 中使用正则表达式