# Watchlist 事件

成员登录后可以指定想要关注的其他成员，连接会在其中任何人上线或下线时收到通知。这就是全部功能：不需要为每段关系建立频道，不需要轮询，只需一个列表。

Watchlist 事件依托[成员登录](/docs/guides/realtime/terminating-member-connections)。后端在登录时签发的身份信息可以携带一个 `watchlist` 成员 id 数组；当应用的 `watchlist_events` 设置开启后，连接会收到这些 id 对应成员的上线和下线事件。一个成员在拥有至少一个已登录连接时即为在线：第一个连接触发 `online`，关闭最后一个连接触发 `offline`，中间的标签页不触发任何事件，与 presence 频道使用的计数逻辑相同。

## 开启功能

在 [**Realtime → Apps**](https://bird.com/dashboard/w/realtime/apps) 页面的应用设置中切换 **Watchlist events**，或通过 Realtime API 将应用的 `watchlist_events` 设置为 `true`。连接在建立时读取该设置，因此请在依赖此功能的客户端上线前完成开启。

## 将 watchlist 放入签名身份信息中

Watchlist 是 `member_data` 的一部分，即成员认证端点签发的 JSON 字符串。在身份信息旁添加 id 列表：

```json
{
  "member_id": "u_1",
  "member_info": { "name": "Ada" },
  "watchlist": ["u_2", "u_3"]
}
```

因为列表位于签名身份信息内部，认证端点决定了成员可以关注谁：请根据你自己的数据（联系人、团队成员）构建数组，而不是接受客户端发送的数组，否则任何成员都可以关注任何其他成员。Watchlist 最多容纳 100 个 id；超出部分会被截断为前 100 个，连接会收到错误 `4302`，其中列出了实际被接受的 id。

列表在登录时捕获，在连接的整个生命周期内有效。要更改列表，让端点签发新的列表：客户端在每次重连时会自动重新登录，因此下一个连接会使用更新后的列表并接收其当前状态。

## 在浏览器中监听

绑定 `bird.member.watchlist`。整个列表的当前状态会在登录后立即到达，因此你可以在任何人状态变化之前就绘制出谁在线：

```typescript
await bird.signin();

bird.member.watchlist.bind("online", (memberIds) => {
  console.log("online:", memberIds);
});
bird.member.watchlist.bind("offline", (memberIds) => {
  console.log("offline:", memberIds);
});
```

每个事件携带它所适用的成员 id。登录后的初始推送覆盖整个列表，按状态分组；之后，事件在成员的连接数在零和一之间变化时到达。

## Watchlist 还是 presence？

Presence 频道回答的是 "who is in this room with me"：所有人订阅同一个频道，看到相同的成员列表。Watchlist 回答的是 "are the people I care about online anywhere"：每个成员关注自己的列表，被关注的人除了登录之外什么都不需要做。好友列表、客服在线指示器或 "your contact just came online" 提醒属于 watchlist 的场景；共享房间的花名册属于 presence。

## 后续步骤

- [终止成员连接](/docs/guides/realtime/terminating-member-connections)涵盖了登录以及 watchlist 所依托的身份信息契约。
- [Presence 频道](/docs/guides/realtime/presence-channels)适用于共享房间的成员关系，而非个人关注列表。
- [向成员发送事件](/docs/guides/realtime/sending-events-to-a-member)是另一个面向成员的接口。

## Related resources

- [Realtime](/products/realtime) (product)
- [Build your first integration](/learn/paths/integration) (course)
- [Send your first realtime event](/docs/get-started/send-your-first-realtime-event) (docs)

[Get an implementation brief](/learn/workspace?topic=realtime)
