适用于 JavaScript 的 Web PubSub 客户端 SDK

注意

有关此处使用的术语的详细信息,请参阅主要概念一文。

客户端 SDK 旨在加快开发人员的工作流;更具体地说,即:

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

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

Screenshot showing clients establishing WebSocket connection with a Web PubSub resource

入门

先决条件

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

npm install @azure/web-pubsub-client

2. 连接 Web PubSub 资源

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

Screenshot showing how to get Client Access Url on Azure portal

如图所示,客户端有权将消息发送到名为 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.

示例

处理 connecteddisconnectedstopped 事件

Azure Web PubSub 会触发 connecteddisconnectedstopped 等系统事件。 可以注册事件处理程序,以确定触发事件时程序应执行的操作。

  1. 当客户端成功连接到 Web PubSub 资源时,将触发 connected 事件。 此代码片段仅输出连接 ID
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 an event handler for the "stopped" event
client.on("stopped", () => {
  console.log(`Client has stopped`);
});

使用应用程序服务器以编程方式生成 Client Access URL

在生产中,客户端通常从应用程序服务器提取 Client Access URL。 服务器将 connection string 保存到 Web PubSub 资源,并借助服务器端库 @azure/web-pubsub 生成 Client Access URL

1. 应用程序服务器

代码片段是应用程序服务器显示 /negotiate 终结点并返回 Client Access 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


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

客户端可以添加回叫以使用来自应用程序服务器或组的消息。

// Registers a listener for the "server-message". The callback is 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 is 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}`);
});

注意

对于 group-message 事件,客户端只能从已加入的组接收消息。

句柄重新加入失败

当客户端断开连接且无法恢复时,将在 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});
}

JavaScript 捆绑包

若要在浏览器中使用此客户端库,需要使用捆绑包。 有关如何创建捆绑包的详细信息,请参阅我们的捆绑文档

疑难解答

启用日志

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

export AZURE_LOG_LEVEL=verbose

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

实时跟踪

使用来自 Azure 门户的实时跟踪工具来检查通过 Web PubSub 资源的实时消息流量。