Sign inGet started

连接生命周期与重连

一个 Realtime 连接就是一个 WebSocket。网络变化、设备休眠和基础设施重启都可能关闭它。客户端会自动重连,而你的应用可以展示当前的连接状态。

六种状态

浏览器客户端中的 bird.connection.state 以及 Swift 和 Kotlin 中的 bird.connectionState 始终是以下值之一(Kotlin 将它们拼写为 ConnectionState 常量,因此 unavailable 读作 ConnectionState.UNAVAILABLE):
状态含义
initialized客户端已创建,但尚未打开 socket。
connectingsocket 正在打开,或已打开并等待握手。
connected握手完成。连接已获得 ID,可以进行订阅。
unavailable连接已断开,重连已排入计划。
disconnected你调用了 disconnect()。没有排入计划的操作。
failed服务器拒绝了此连接。客户端不会重试。
绑定 state_change 可监听每次状态转换,或者只绑定某个状态名称来监听特定状态:
import { BirdRealtime } from "@messagebird/realtime";

const bird = new BirdRealtime({ appKey: "your-app-key", region: "us1" });

bird.connection.bind("state_change", ({ previous, current }) => {
  console.log(previous, "->", current);
});

bird.connection.bind("unavailable", () => showReconnectingBanner());
bird.connection.bind("connected", () => hideReconnectingBanner());
Swift 和 Kotlin 使用同一个观察者监听所有状态转换,因此需要对 current 进行分支判断。处理函数在 Swift 中运行于主队列,在 Kotlin 中运行于 Android 主 looper(如果可用)。传入 deliveryQueueExecutor 可切换到其他执行上下文。
已打开的 socket 在服务器握手到达之前一直处于 connecting 状态。握手在状态变为 connected 之前设置 bird.connection.connectionId,因此授权可以对该 ID 进行签名。如果握手未携带 ID,客户端会报告错误并关闭 socket。

自动重连

在意外断开后,客户端会等待一段时间再打开新的 socket。延迟采用全抖动指数退避策略,基数为 1 秒,上限为 30 秒。每次握手成功都会重置退避计数。
关闭码决定了以下三种情况中的哪一种:
关闭码行为
40004099拒绝。不重试,状态变为 failed
42004299立即重试。
其他所有值状态变为 unavailable,然后按退避策略重试。
网络故障走退避路径。请在你的 UI 中处理拒绝码,因为这些终态失败不会自动重连。

过期连接检测

网络路径失效后,socket 可能仍显示为已打开。客户端会在活动超时后发送 ping,默认为 120 秒,除非握手提供了其他值。如果在 30 秒的默认 pong 超时内没有收到 pong,客户端将使用立即重试码关闭 socket。

频道会发生什么

订阅属于连接,因此断开会移除它们。客户端会保留每个频道对象,在下一次进入 connected 状态后重新订阅,并保持已有的处理函数。
客户端会使用新的连接 ID 为每个私有频道和 presence 频道再次调用你的 authEndpoint。它无法复用旧签名,因为该签名包含了上一个连接 ID。在一次 signin() 调用后,客户端也会在每次新连接上进行登录,并通过 signin_error 报告后续失败。
bird.connection.bind("signin_error", ({ message }) => {
  console.warn("connection has no identity:", message);
});
当频道正在重连时,channel.trigger 返回 false 但不会发送客户端事件。请检查 channel.subscribed,或者在 bird:subscription_succeeded 之后再发送,该事件在每次成功重新订阅后触发。
const room = bird.subscribe("presence-room-1");

room.bind("bird:subscription_succeeded", ({ members }) => {
  renderMembers(members);
});
Realtime 不会重放客户端断开期间发布的事件。如果视图需要在断开后恢复,请在 bird:subscription_succeeded 时获取当前状态,然后从该点开始应用后续事件。

主动断开连接

bird.disconnect() 关闭 socket 且不排入重连计划。当已登出或不活跃的客户端不再需要实时数据时使用它。客户端会保留频道,因此稍后调用 bird.connect() 可重新打开 socket 并重新订阅。
bird.disconnect(); // state: disconnected, no reconnect
bird.connect(); // reopens and re-subscribes
在移动端,当相关视图或 activity 停止时断开连接,恢复时重连。频道对象和绑定仍然可用。

连接上的错误与频道上的错误

属于某个频道的服务器错误会到达该频道。最常见的是订阅被拒绝,以及身份验证器返回 403 的情况:
room.bind("bird:subscription_error", (err) => {
  console.warn("could not join:", err);
});
所有未被归属到某个频道的线路数据都会到达连接:
bird.connection.bind("error", ({ code, message }) => {
  console.warn(code, message);
});

处理关闭码 4009

4009 属于不重试区间,因此连接进入 failed。检查原因以区分以下情况:
  • 被终止的成员。 你的后端为该成员调用了断开连接 API,因此其持有的所有连接都被关闭。参阅终止成员连接
  • 从未授权的连接。 应用要求授权连接,而此连接未在规定时间内完成授权。参阅要求授权连接
客户端不会自动重连,因此由你的应用决定下一步操作:
bird.connection.bind("error", ({ code }) => {
  if (code === 4009) showSignedOutScreen();
});
当身份验证已结束时,适合进入已登出状态。调用 bird.connect() 会启动新连接并重复授权流程,因此仅在调用者的授权状态发生变化后再重连。

后续步骤