你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

适用于 JavaScript 的 Web PubSub 客户端库

Azure Web PubSub 是一项云服务,可帮助开发人员使用发布-订阅模式大规模在 Web 应用程序中轻松构建实时功能。

任何需要在服务器和客户端之间或在遵循发布-订阅模式的客户端之间进行实时消息传送的方案都可以受益于使用 Web PubSub。 开发人员不再需要通过每隔一段时间发送重复的 HTTP 请求来轮询服务器,这是浪费且难以缩放的。

如下图所示,客户端与 Web PubSub 资源建立 WebSocket 连接。 此客户端库:

  • 简化客户端连接的管理
  • 简化在客户端之间发送消息
  • 在意外删除客户端连接后自动重试
  • 从连接断开恢复后,按数量和顺序可靠地传递消息

溢出

有关此处使用的术语的详细信息,请参阅 关键概念 部分。

此库托管在 NPM 上。


入门

目前支持的环境

先决条件

1. 安装 @azure/web-pubsub-client

npm install @azure/web-pubsub-client

2. 连接 Web PubSub 资源

客户端使用客户端访问 URL 以连接服务并对其进行身份验证,该过程遵循 wss://<service_name>.webpubsub.azure.com/client/hubs/<hub_name>?access_token=<token> 模式。 客户端可以通过几种方式获取客户端访问 URL。 对于本快速入门,可以从 Azure 门户复制并粘贴一个,如下所示。 (对于生产,客户端通常会在应用程序服务器上获取生成客户端访问 URL。 请参阅下面的详细信息 )

get_client_url

如上图所示,客户端有权向名为“group1”的特定组发送消息并加入该组。

// Imports the client libray
const { WebPubSubClient } = require("@azure/web-pubsub-client");

// Instantiates the client object
const client = new WebPubSubClient("<client-access-url>");

// Starts the client connection with your Web PubSub resource
await client.start();

// ...
// The client can join/leave groups, send/receive messages to and from those groups all in real-time

3. 加入组

请注意,客户端只能从已加入的组接收消息,你需要添加回调以在接收消息时指定逻辑。

// ...continues the code snippet from above

// Specifies the group to join
let groupName = "group1";

// Registers a listener for the event 'group-message' early before joining a group to not miss messages
client.on("group-message", (e) => {
  console.log(`Received message: ${e.message.data}`);
});

// A client needs to join the group it wishes to receive messages from
await client.joinGroup(groupName);

4. 向组发送消息

// ...continues the code snippet from above

// Send a message to a joined group
await client.sendToGroup(groupName, "hello world", "text");

// In the Console tab of your developer tools found in your browser, you should see the message printed there.

示例

为已连接、已断开连接和已停止事件添加回调

  1. 当客户端成功连接到 Web PubSub 资源时,将触发 connected 事件。
client.on("connected", (e) => {
  console.log(`Connection ${e.connectionId} is connected.`);
});
  1. 当客户端断开连接且无法恢复连接时,将触发 disconnected 事件。
client.on("disconnected", (e) => {
  console.log(`Connection disconnected: ${e.message}`);
});
  1. stopped 客户端断开连接 客户端停止尝试重新连接时,将触发 该事件。 这通常发生在调用 client.stop()、禁用 autoReconnect 或达到尝试重新连接时的指定限制之后。 如果要重启客户端,可以在已停止事件中调用 client.start()
// Registers a listener for the "stopped" event
client.on("stopped", () => {
  console.log(`Client has stopped`);
});

使用协商服务器以编程方式生成客户端访问 URL

在生产环境中,客户端通常从应用程序服务器提取客户端访问 URL。 服务器将连接字符串保存到 Web PubSub 资源,并在服务器库 @azure/web-pubsub的帮助下生成客户端访问 URL。

1. 应用程序服务器

下面的代码片段是应用程序服务器公开 /negotiate 路径并返回客户端访问 URL 的示例。

// This code snippet uses the popular Express framework
const express = require('express');
const app = express();
const port = 8080;

// Imports the server library, which is different from the client library
const { WebPubSubServiceClient } = require('@azure/web-pubsub');
const hubName = 'sample_chat';

const serviceClient = new WebPubSubServiceClient("<web-pubsub-connectionstring>", hubName);

// Note that the token allows the client to join and send messages to any groups. It is specified with the "roles" option.
app.get('/negotiate', async (req, res) => {
  let token = await serviceClient.getClientAccessToken({roles: ["webpubsub.joinLeaveGroup", "webpubsub.sendToGroup"] });
  res.json({
    url: token.url
  });
});

app.listen(port, () => console.log(`Application server listening at http://localhost:${port}/negotiate`));

2. 客户端

下面的代码片段是客户端的示例。

const { WebPubSubClient } = require("@azure/web-pubsub-client")

const client = new WebPubSubClient({
  getClientAccessUrl: async () => {
    let value = await (await fetch(`/negotiate`)).json();
    return value.url;
  }
});

await client.start();

若要查看此示例的完整代码,请参阅 samples-browser


客户端使用来自应用程序服务器或已加入组的消息

客户端可以添加回调以使用来自应用程序服务器或组的消息。 请注意,对于 group-message 事件,客户端 只能 接收已加入的组消息。

// Registers a listener for the "server-message". The callback will be invoked when your application server sends message to the connectionID, to or broadcast to all connections.
client.on("server-message", (e) => {
  console.log(`Received message ${e.message.data}`);
});

// Registers a listener for the "group-message". The callback will be invoked when the client receives a message from the groups it has joined.
client.on("group-message", (e) => {
    console.log(`Received message from ${e.message.group}: ${e.message.data}`);
});

句柄重新加入失败

当客户端断开连接且无法恢复时,将在 Web PubSub 资源中清理所有组上下文。 这意味着客户端重新连接时,需要重新加入组。 默认情况下,客户端已启用 autoRejoinGroup 选项。

但是,应注意 autoRejoinGroup 的限制。

  • 客户端只能重新加入最初由 客户端代码而不是 服务器端代码联接的组。
  • “重新加入组”操作可能会由于各种原因而失败,例如客户端无权加入组。 在这种情况下,需要添加回叫来处理此问题。
// By default autoRejoinGroups=true. You can disable it by setting to false.
const client = new WebPubSubClient("<client-access-url>", { autoRejoinGroups: true });

// Registers a listener to handle "rejoin-group-failed" event
client.on("rejoin-group-failed", e => {
  console.log(`Rejoin group ${e.group} failed: ${e.error}`);
})

操作和重试

默认情况下,操作(如 client.joinGroup()client.leaveGroup()client.sendToGroup()client.sendEvent())有三次重试机会。 可以通过messageRetryOptions进行配置。 如果所有重试都失败,将引发错误。 可以通过传入与之前的重试相同的 ackId 来继续重试,以便 Web PubSub 服务可以删除重复操作。

try {
  await client.joinGroup(groupName);
} catch (err) {
  let id = null;
  if (err instanceof SendMessageError) {
    id = err.ackId;
  }
  await client.joinGroup(groupName, {ackId: id});
}

指定子协议

可以更改客户端要使用的子协议。 默认情况下,客户端使用 json.reliable.webpubsub.azure.v1。 可以选择使用 json.reliable.webpubsub.azure.v1json.webpubsub.azure.v1

// Change to use json.webpubsub.azure.v1
const client = new WebPubSubClient("<client-access-url>", { protocol: WebPubSubJsonProtocol() });
// Change to use json.reliable.webpubsub.azure.v1
const client = new WebPubSubClient("<client-access-url>", { protocol: WebPubSubJsonReliableProtocol() });

关键概念

连接

连接(也称为客户端或客户端连接)表示连接到 Web PubSub 的单个 WebSocket 连接。 成功连接后,Web PubSub 会向此连接分配唯一的连接 ID。 每个都 WebPubSubClient 创建自己的独占连接。

恢复

如果使用可靠协议的客户端断开连接,则新的 WebSocket 会尝试使用丢失的连接的连接 ID 建立连接。 如果成功连接新的 WebSocket 连接,则恢复该连接。 在客户端断开连接期间,服务会保留客户端的上下文以及客户端订阅的所有消息,当客户端恢复时,服务会将这些消息发送到客户端。 如果服务返回 WebSocket 错误代码 1008 或恢复尝试持续时间超过 30 秒,则恢复将失败。

重新连接

当客户端连接断开且无法恢复时,会发生重新连接。 重新连接将启动新连接,新连接具有新的连接 ID。 与恢复不同,服务将重新连接的客户端视为新的客户端连接。 客户端连接需要重新加入组。 默认情况下,客户端库在重新连接后重新加入组。

集线器

中心是客户端连接集的逻辑概念。 通常,将一个中心用于一个目的,例如聊天中心或通知中心。 创建客户端连接后,它会连接到某个中心,并且在其生存期内属于该中心。 不同的应用程序可以通过使用不同的中心名称共享一个 Web PubSub。

组是与中心的连接的子集。 可以随时向组添加客户端连接或者从组中删除客户端连接。 例如,当某个客户端加入聊天室,或某个客户端离开聊天室,此类聊天室可以看成是一个组。 一个客户端可以加入多个组,一个组可以包含多个客户端。

用户

与 Web PubSub 的连接可以属于一个用户。 用户可能具有多个连接,例如当单个用户跨多个设备或多个浏览器选项卡进行连接时。


客户端生存期

每个 Web PubSub 客户端都可以安全地缓存,并在应用程序的生存期内用作单一实例。 已注册的事件回调与客户端共享相同的生存期。 这意味着可以随时添加或删除回调,注册状态在重新连接或客户端停止后不会更改。


JavaScript 捆绑包

若要在浏览器中使用此客户端库,首先需要使用捆绑程序。 有关如何执行此操作的详细信息,请参阅捆绑 文档


疑难解答

  • 启用日志

    使用此库时,可设置以下环境变量来获取调试日志。

export AZURE_LOG_LEVEL=verbose

有关如何启用日志的更详细说明,请查看 @azure/logger 包文档


其他资源


贡献

若要为此库做出贡献,请阅读贡献指南,详细了解如何生成和测试代码。