@8base/subscriptions-transport-ws 中文文档教程

发布于 3年前 浏览 26 项目主页 更新于 3年前

npm 版本GitHub license

subscriptions-transport-ws

(正在进行中!)

一个 GraphQL WebSocket 服务器和客户端,以促进 GraphQL通过 WebSocket 进行查询、变更和订阅。

subscriptions-transport-ws 是 GraphQL 的扩展,您可以将它与任何 GraphQL 客户端和服务器(不仅是 Apollo)一起使用。

请参阅 GitHunt-APIGitHunt -React 用于示例服务器和客户端集成。

Getting Started

首先使用 Yarn 或 NPM 安装包。

Using Yarn:
$ yarn add subscriptions-transport-ws

Or, using NPM:
$ npm install --save subscriptions-transport-ws

请注意,您需要在 GraphQL 客户端和服务器上使用此包。

此命令还会安装此包的依赖项,包括 graphql-subscriptions

Server

从服务器开始,创建一个新的简单 PubSub 实例。 我们稍后将使用此 PubSub 来发布和订阅数据更改。

import { PubSub } from 'graphql-subscriptions';

export const pubsub = new PubSub();

现在,使用您的 GraphQL schemaexecutesubscribe 创建 SubscriptionServer 实例(来自 graphql-js 包):

import { createServer } from 'http';
import { SubscriptionServer } from 'subscriptions-transport-ws';
import { execute, subscribe } from 'graphql';
import { schema } from './my-schema';

const WS_PORT = 5000;

// Create WebSocket listener server
const websocketServer = createServer((request, response) => {
  response.writeHead(404);
  response.end();
});

// Bind it to port and start listening
websocketServer.listen(WS_PORT, () => console.log(
  `Websocket Server is now running on http://localhost:${WS_PORT}`
));

const subscriptionServer = SubscriptionServer.create(
  {
    schema,
    execute,
    subscribe,
  },
  {
    server: websocketServer,
    path: '/graphql',
  },
);

Creating Your Subscriptions

请参考 graphql-subscriptions 文档了解如何创建您的GraphQL 订阅,以及如何发布数据。

Client (browser)

将此包用于客户端时,您可以选择将 HTTP 请求用于查询和变异并仅将 WebSocket 用于订阅,或者创建一个完整的传输来处理套接字上所有类型的 GraphQL 操作。

Full WebSocket Transport

要从处理所有类型的 GraphQL 操作的完整 WebSocket 传输开始,导入并创建 SubscriptionClient 的实例。

然后,创建您的 ApolloClient 实例并使用 SubscriptionsClient 实例作为网络接口:

import { SubscriptionClient } from 'subscriptions-transport-ws';
import ApolloClient from 'apollo-client';

const GRAPHQL_ENDPOINT = 'ws://localhost:3000/graphql';

const client = new SubscriptionClient(GRAPHQL_ENDPOINT, {
  reconnect: true,
});

const apolloClient = new ApolloClient({
    networkInterface: client,
});

Hybrid WebSocket Transport

从混合 WebSocket 传输开始,它仅处理 subscription WebSocket,创建你的 SubscriptionClient 和一个常规的 HTTP 网络接口,然后扩展你的网络接口以使用 WebSocket 客户端进行 GraphQL 订阅:

import {SubscriptionClient, addGraphQLSubscriptions} from 'subscriptions-transport-ws';
import ApolloClient, {createNetworkInterface} from 'apollo-client';

// Create regular NetworkInterface by using apollo-client's API:
const networkInterface = createNetworkInterface({
 uri: 'http://localhost:3000' // Your GraphQL endpoint
});

// Create WebSocket client
const wsClient = new SubscriptionClient(`ws://localhost:5000/`, {
    reconnect: true,
    connectionParams: {
        // Pass any arguments you want for initialization
    }
});

// Extend the network interface with the WebSocket
const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
    networkInterface,
    wsClient
);

// Finally, create your ApolloClient instance with the modified network interface
const apolloClient = new ApolloClient({
    networkInterface: networkInterfaceWithSubscriptions
});

现在,当你想在客户端使用订阅时,使用你的 ApolloClient 实例,带有 subscribe查询 subscribeToMore:

apolloClient.subscribe({
  query: gql`
    subscription onNewItem {
        newItemCreated {
            id
        }
    }`,
  variables: {}
}).subscribe({
  next (data) {
    // Notify your application with the new arrived data
  }
});
apolloClient.query({
  query: ITEM_LIST_QUERY,
  variables: {}
}).subscribeToMore({
  document: gql`
    subscription onNewItem {
        newItemCreated {
            id
        }
    }`,
  variables: {},
  updateQuery: (prev, { subscriptionData, variables }) => {
    // Perform updates on previousResult with subscriptionData
    return updatedResult;
  }
});

如果你不使用任何包/模块加载器,你仍然可以使用这个包,通过使用 unpkg 服务,并从以下位置获取客户端包:

https://unpkg.com/subscriptions-transport-ws@VERSION/browser/client.js

将 VERSION 替换为包的最新版本.

Use it with GraphiQL

您可以将此包的功能与 GraphiQL 结合使用,并在 GraphiQL 中订阅实时数据流。

如果您使用的是最新版本的 graphql-server 风格(graphql-server-expressgraphql-server-koa 等),你已经可以使用它了! 确保在 GraphiQL 配置中指定 subscriptionsEndpoint,仅此而已!

例如,graphql-server-express 用户需要添加以下内容:

app.use('/graphiql', graphiqlExpress({
  endpointURL: '/graphql',
  subscriptionsEndpoint: `YOUR_SUBSCRIPTION_ENDPOINT_HERE`,
}));

如果您使用的是旧版本或其他 GraphQL 服务器,请从修改 GraphiQL 静态 HTML 开始,然后添加此包及其从 CDN 获取的内容:

    <script src="//unpkg.com/subscriptions-transport-ws@0.5.4/browser/client.js"></script>
    <script src="//unpkg.com/graphiql-subscriptions-fetcher@0.0.2/browser/client.js"></script>

然后,创建 SubscriptionClient 并定义 fetcher:

let subscriptionsClient = new window.SubscriptionsTransportWs.SubscriptionClient('SUBSCRIPTION_WS_URL_HERE', {
  reconnect: true
});
let myCustomFetcher = window.GraphiQLSubscriptionsFetcher.graphQLFetcher(subscriptionsClient, graphQLFetcher);

graphQLFetcher 是默认的 fetcher,我们将其用作非订阅 GraphQL 操作的后备。

并替换您的 GraphiQL 创建逻辑以使用新的

ReactDOM.render(
  React.createElement(GraphiQL, {
    fetcher: myCustomFetcher, // <-- here
    onEditQuery: onEditQuery,
    onEditVariables: onEditVariables,
    onEditOperationName: onEditOperationName,
    query: ${safeSerialize(queryString)},
    response: ${safeSerialize(resultString)},
    variables: ${safeSerialize(variablesString)},
    operationName: ${safeSerialize(operationName)},
  }),
  document.body
);

API Docs

SubscriptionClient

Constructor(url, options, webSocketImpl)

  • url: string : url that the client will connect to, starts with ws:// or wss://
  • options?: Object : optional, object to modify default client behavior
  • timeout?: number : how long the client should wait in ms for a keep-alive message from the server (default 30000 ms), this parameter is ignored if the server does not send keep-alive messages. This will also be used to calculate the max connection time per connect/reconnect
  • lazy?: boolean : use to set lazy mode - connects only when first subscription created, and delay the socket initialization
  • connectionParams?: Object | Function | Promise<Object> : object that will be available as first argument of onConnect (in server side), if passed a function - it will call it and send the return value, if function returns as promise - it will wait until it resolves and send the resolved value.
  • reconnect?: boolean : automatic reconnect in case of connection error
  • reconnectionAttempts?: number : how much reconnect attempts
  • connectionCallback?: (error) => {} : optional, callback that called after the first init message, with the error (if there is one)
  • inactivityTimeout?: number : how long the client should wait in ms, when there are no active subscriptions, before disconnecting from the server. Set to 0 to disable this behavior. (default 0)
  • webSocketImpl?: Object - optional, constructor for W3C compliant WebSocket implementation. Use this when your environment does not have a built-in native WebSocket (for example, with NodeJS client)

Methods

request(options) => Observable<ExecutionResult>: returns observable to execute the operation.

  • options: {OperationOptions}
  • query: string : GraphQL subscription
  • variables: Object : GraphQL subscription variables
  • operationName: string : operation name of the subscription
  • context: Object : use to override context for a specific call

unsubscribeAll() => void - unsubscribes from all active subscriptions.

on(eventName, callback, thisContext) => Function

  • eventName: string: the name of the event, available events are: connecting, connected, reconnecting, reconnected, disconnected and error
  • callback: Function: function to be called when websocket connects and initialized.
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

onConnected(callback, thisContext) => Function - shorthand for .on('connected', ...)

  • callback: Function: function to be called when websocket connects and initialized, after ACK message returned from the server
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

onReconnected(callback, thisContext) => Function - shorthand for .on('reconnected', ...)

  • callback: Function: function to be called when websocket reconnects and initialized, after ACK message returned from the server
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

onConnecting(callback, thisContext) => Function - shorthand for .on('connecting', ...)

  • callback: Function: function to be called when websocket starts it's connection
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

onReconnecting(callback, thisContext) => Function - shorthand for .on('reconnecting', ...)

  • callback: Function: function to be called when websocket starts it's reconnection
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

onDisconnected(callback, thisContext) => Function - shorthand for .on('disconnected', ...)

  • callback: Function: function to be called when websocket disconnected.
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

onError(callback, thisContext) => Function - shorthand for .on('error', ...)

  • callback: Function: function to be called when an error occurs.
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

close() => void - closes the WebSocket connection manually, and ignores reconnect logic if it was set to true.

use(middlewares: MiddlewareInterface[]) => SubscriptionClient - adds middleware to modify OperationOptions per each request

  • middlewares: MiddlewareInterface[] - Array contains list of middlewares (implemented applyMiddleware method) implementation, the SubscriptionClient will use the middlewares to modify OperationOptions for every operation

status: number : returns the current socket's readyState

SubscriptionServer

Constructor(options, socketOptions | socketServer)

  • 提取

  • 器 : GraphQLSchema : GraphQL 模式对象。 如果未提供,您必须将架构作为从 onOperation 返回的对象的属性返回。

  • execute?: (schema, document, rootValue, contextValue, variableValues, operationName) => Promise<执行结果> | AsyncIterator : GraphQL execute 函数,graphql 包中提供了默认的函数。 AsyncItrator 的返回值也是有效的,因为这个包也支持响应式 execute 方法。

  • subscribe?: (schema, document, rootValue, contextValue, variableValues, operationName) => Promise<执行结果 | AsyncIterator> : GraphQL subscribe 函数,默认提供graphql包。

  • onOperation?: (message: SubscribeMessage, params: SubscriptionOptions, webSocket: WebSocket) :创建自定义参数的可选方法,将在解析此操作时使用。 它还可用于动态解析将用于特定操作的模式。

  • onOperationComplete?: (webSocket: WebSocket, opId: string) :当 GraphQL 操作完成时调用的可选方法(对于查询和变异它是立即的,对于取消订阅时的订阅)

  • onConnect?: (connectionParams: Object, webSocket: WebSocket, context: ConnectionContext) :当客户端连接到套接字时调用的可选方法,如果返回值为一个对象,它的元素将被添加到上下文中。 返回 false 或抛出异常以拒绝连接。 可以返回一个 Promise。

  • : WebSocket, context: ConnectionContext) :客户端断开连接时调用的可选方法

  • onDisconnect?: ( webSocket 给所有客户端的消息

  • socketOptions: {WebSocket.IServerOptions} : 传递给 WebSocket 对象的选项blob/master/doc/ws.md">here)

  • server?: HttpServer - 要使用的现有 HTTP 服务器(不使用 host/port)

  • host?: string - 服务器主机

  • port?: number - 服务器端口

  • path?: string - 端点路径

  • socketServer: {WebSocket.Server} :如果您需要更多控制,则配置服务器。 可用于与内存中 WebSocket 实现的集成测试。

How it works?

此传输的当前版本,还支持以前版本的协议。

你可以在这里找到旧的协议文档

npm versionGitHub license

subscriptions-transport-ws

(Work in progress!)

A GraphQL WebSocket server and client to facilitate GraphQL queries, mutations and subscriptions over WebSocket.

subscriptions-transport-ws is an extension for GraphQL, and you can use it with any GraphQL client and server (not only Apollo).

See GitHunt-API and GitHunt-React for an example server and client integration.

Getting Started

Start by installing the package, using Yarn or NPM.

Using Yarn:
$ yarn add subscriptions-transport-ws

Or, using NPM:
$ npm install --save subscriptions-transport-ws

Note that you need to use this package on both GraphQL client and server.

This command also installs this package's dependencies, including graphql-subscriptions.

Server

Starting with the server, create a new simple PubSub instance. We will later use this PubSub to publish and subscribe to data changes.

import { PubSub } from 'graphql-subscriptions';

export const pubsub = new PubSub();

Now, create SubscriptionServer instance, with your GraphQL schema, execute and subscribe (from graphql-js package):

import { createServer } from 'http';
import { SubscriptionServer } from 'subscriptions-transport-ws';
import { execute, subscribe } from 'graphql';
import { schema } from './my-schema';

const WS_PORT = 5000;

// Create WebSocket listener server
const websocketServer = createServer((request, response) => {
  response.writeHead(404);
  response.end();
});

// Bind it to port and start listening
websocketServer.listen(WS_PORT, () => console.log(
  `Websocket Server is now running on http://localhost:${WS_PORT}`
));

const subscriptionServer = SubscriptionServer.create(
  {
    schema,
    execute,
    subscribe,
  },
  {
    server: websocketServer,
    path: '/graphql',
  },
);

Creating Your Subscriptions

Please refer to graphql-subscriptions documentation for how to create your GraphQL subscriptions, and how to publish data.

Client (browser)

When using this package for client side, you can choose either use HTTP request for Queries and Mutation and use the WebSocket for subscriptions only, or create a full transport that handles all type of GraphQL operations over the socket.

Full WebSocket Transport

To start with a full WebSocket transport, that handles all types of GraphQL operations, import and create an instance of SubscriptionClient.

Then, create your ApolloClient instance and use the SubscriptionsClient instance as network interface:

import { SubscriptionClient } from 'subscriptions-transport-ws';
import ApolloClient from 'apollo-client';

const GRAPHQL_ENDPOINT = 'ws://localhost:3000/graphql';

const client = new SubscriptionClient(GRAPHQL_ENDPOINT, {
  reconnect: true,
});

const apolloClient = new ApolloClient({
    networkInterface: client,
});

Hybrid WebSocket Transport

To start with a hybrid WebSocket transport, that handles only subscriptions over WebSocket, create your SubscriptionClient and a regular HTTP network interface, then extend your network interface to use the WebSocket client for GraphQL subscriptions:

import {SubscriptionClient, addGraphQLSubscriptions} from 'subscriptions-transport-ws';
import ApolloClient, {createNetworkInterface} from 'apollo-client';

// Create regular NetworkInterface by using apollo-client's API:
const networkInterface = createNetworkInterface({
 uri: 'http://localhost:3000' // Your GraphQL endpoint
});

// Create WebSocket client
const wsClient = new SubscriptionClient(`ws://localhost:5000/`, {
    reconnect: true,
    connectionParams: {
        // Pass any arguments you want for initialization
    }
});

// Extend the network interface with the WebSocket
const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
    networkInterface,
    wsClient
);

// Finally, create your ApolloClient instance with the modified network interface
const apolloClient = new ApolloClient({
    networkInterface: networkInterfaceWithSubscriptions
});

Now, when you want to use subscriptions in client side, use your ApolloClient instance, with subscribe or query subscribeToMore:

apolloClient.subscribe({
  query: gql`
    subscription onNewItem {
        newItemCreated {
            id
        }
    }`,
  variables: {}
}).subscribe({
  next (data) {
    // Notify your application with the new arrived data
  }
});
apolloClient.query({
  query: ITEM_LIST_QUERY,
  variables: {}
}).subscribeToMore({
  document: gql`
    subscription onNewItem {
        newItemCreated {
            id
        }
    }`,
  variables: {},
  updateQuery: (prev, { subscriptionData, variables }) => {
    // Perform updates on previousResult with subscriptionData
    return updatedResult;
  }
});

If you don't use any package/modules loader, you can still use this package, by using unpkg service, and get the client side package from:

https://unpkg.com/subscriptions-transport-ws@VERSION/browser/client.js

Replace VERSION with the latest version of the package.

Use it with GraphiQL

You can use this package's power with GraphiQL, and subscribe to live-data stream inside GraphiQL.

If you are using the latest version of graphql-server flavors (graphql-server-express, graphql-server-koa, etc…), you already can use it! Make sure to specify subscriptionsEndpoint in GraphiQL configuration, and that's it!

For example, graphql-server-express users need to add the following:

app.use('/graphiql', graphiqlExpress({
  endpointURL: '/graphql',
  subscriptionsEndpoint: `YOUR_SUBSCRIPTION_ENDPOINT_HERE`,
}));

If you are using older version, or another GraphQL server, start by modifying GraphiQL static HTML, and add this package and it's fetcher from CDN:

    <script src="//unpkg.com/subscriptions-transport-ws@0.5.4/browser/client.js"></script>
    <script src="//unpkg.com/graphiql-subscriptions-fetcher@0.0.2/browser/client.js"></script>

Then, create SubscriptionClient and define the fetcher:

let subscriptionsClient = new window.SubscriptionsTransportWs.SubscriptionClient('SUBSCRIPTION_WS_URL_HERE', {
  reconnect: true
});
let myCustomFetcher = window.GraphiQLSubscriptionsFetcher.graphQLFetcher(subscriptionsClient, graphQLFetcher);

graphQLFetcher is the default fetcher, and we use it as fallback for non-subscription GraphQL operations.

And replace your GraphiQL creation logic to use the new fetcher:

ReactDOM.render(
  React.createElement(GraphiQL, {
    fetcher: myCustomFetcher, // <-- here
    onEditQuery: onEditQuery,
    onEditVariables: onEditVariables,
    onEditOperationName: onEditOperationName,
    query: ${safeSerialize(queryString)},
    response: ${safeSerialize(resultString)},
    variables: ${safeSerialize(variablesString)},
    operationName: ${safeSerialize(operationName)},
  }),
  document.body
);

API Docs

SubscriptionClient

Constructor(url, options, webSocketImpl)

  • url: string : url that the client will connect to, starts with ws:// or wss://
  • options?: Object : optional, object to modify default client behavior
  • timeout?: number : how long the client should wait in ms for a keep-alive message from the server (default 30000 ms), this parameter is ignored if the server does not send keep-alive messages. This will also be used to calculate the max connection time per connect/reconnect
  • lazy?: boolean : use to set lazy mode - connects only when first subscription created, and delay the socket initialization
  • connectionParams?: Object | Function | Promise<Object> : object that will be available as first argument of onConnect (in server side), if passed a function - it will call it and send the return value, if function returns as promise - it will wait until it resolves and send the resolved value.
  • reconnect?: boolean : automatic reconnect in case of connection error
  • reconnectionAttempts?: number : how much reconnect attempts
  • connectionCallback?: (error) => {} : optional, callback that called after the first init message, with the error (if there is one)
  • inactivityTimeout?: number : how long the client should wait in ms, when there are no active subscriptions, before disconnecting from the server. Set to 0 to disable this behavior. (default 0)
  • webSocketImpl?: Object - optional, constructor for W3C compliant WebSocket implementation. Use this when your environment does not have a built-in native WebSocket (for example, with NodeJS client)

Methods

request(options) => Observable<ExecutionResult>: returns observable to execute the operation.

  • options: {OperationOptions}
  • query: string : GraphQL subscription
  • variables: Object : GraphQL subscription variables
  • operationName: string : operation name of the subscription
  • context: Object : use to override context for a specific call

unsubscribeAll() => void - unsubscribes from all active subscriptions.

on(eventName, callback, thisContext) => Function

  • eventName: string: the name of the event, available events are: connecting, connected, reconnecting, reconnected, disconnected and error
  • callback: Function: function to be called when websocket connects and initialized.
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

onConnected(callback, thisContext) => Function - shorthand for .on('connected', ...)

  • callback: Function: function to be called when websocket connects and initialized, after ACK message returned from the server
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

onReconnected(callback, thisContext) => Function - shorthand for .on('reconnected', ...)

  • callback: Function: function to be called when websocket reconnects and initialized, after ACK message returned from the server
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

onConnecting(callback, thisContext) => Function - shorthand for .on('connecting', ...)

  • callback: Function: function to be called when websocket starts it's connection
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

onReconnecting(callback, thisContext) => Function - shorthand for .on('reconnecting', ...)

  • callback: Function: function to be called when websocket starts it's reconnection
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

onDisconnected(callback, thisContext) => Function - shorthand for .on('disconnected', ...)

  • callback: Function: function to be called when websocket disconnected.
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

onError(callback, thisContext) => Function - shorthand for .on('error', ...)

  • callback: Function: function to be called when an error occurs.
  • thisContext: any: this context to use when calling the callback function.
  • => Returns an off method to cancel the event subscription.

close() => void - closes the WebSocket connection manually, and ignores reconnect logic if it was set to true.

use(middlewares: MiddlewareInterface[]) => SubscriptionClient - adds middleware to modify OperationOptions per each request

  • middlewares: MiddlewareInterface[] - Array contains list of middlewares (implemented applyMiddleware method) implementation, the SubscriptionClient will use the middlewares to modify OperationOptions for every operation

status: number : returns the current socket's readyState

SubscriptionServer

Constructor(options, socketOptions | socketServer)

  • options: {ServerOptions}

  • rootValue?: any : Root value to use when executing GraphQL root operations

  • schema?: GraphQLSchema : GraphQL schema object. If not provided, you have to return the schema as a property on the object returned from onOperation.

  • execute?: (schema, document, rootValue, contextValue, variableValues, operationName) => Promise<ExecutionResult> | AsyncIterator<ExecutionResult> : GraphQL execute function, provide the default one from graphql package. Return value of AsyncItrator is also valid since this package also support reactive execute methods.

  • subscribe?: (schema, document, rootValue, contextValue, variableValues, operationName) => Promise<ExecutionResult | AsyncIterator<ExecutionResult>> : GraphQL subscribe function, provide the default one from graphql package.

  • onOperation?: (message: SubscribeMessage, params: SubscriptionOptions, webSocket: WebSocket) : optional method to create custom params that will be used when resolving this operation. It can also be used to dynamically resolve the schema that will be used for the particular operation.

  • onOperationComplete?: (webSocket: WebSocket, opId: string) : optional method that called when a GraphQL operation is done (for query and mutation it's immediately, and for subscriptions when unsubscribing)

  • onConnect?: (connectionParams: Object, webSocket: WebSocket, context: ConnectionContext) : optional method that called when a client connects to the socket, called with the connectionParams from the client, if the return value is an object, its elements will be added to the context. return false or throw an exception to reject the connection. May return a Promise.

  • onDisconnect?: (webSocket: WebSocket, context: ConnectionContext) : optional method that called when a client disconnects

  • keepAlive?: number : optional interval in ms to send KEEPALIVE messages to all clients

  • socketOptions: {WebSocket.IServerOptions} : options to pass to the WebSocket object (full docs here)

  • server?: HttpServer - existing HTTP server to use (use without host/port)

  • host?: string - server host

  • port?: number - server port

  • path?: string - endpoint path

  • socketServer: {WebSocket.Server} : a configured server if you need more control. Can be used for integration testing with in-memory WebSocket implementation.

How it works?

The current version of this transport, also support a previous version of the protocol.

You can find the old protocol docs here

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文