事件與錯誤處理
Web SDK 用事件通知你資料和狀態的變化,用 DRError 報告所有的錯誤。本頁列出全部事件和它們的載荷、錯誤物件的結構、全部錯誤碼與處理建議,以及 SDK 在離線和出錯時自動做了什麼。
大多數介面不需要直接處理資料變化的事件:會話列表、訊息列表等可訂閱的列表會自動更新。事件主要用於三類場景:登入和連線狀態的變化(回到登入頁、顯示“連線中”),提醒(新訊息通知、來電),以及讀取同步狀態的值(未讀總數、正在輸入等)時得知何時重新讀取。
| 要做什麼 | 看哪裡 |
|---|---|
| 訂閱和取消事件 | 訂閱與取消 |
| 查某個事件的載荷 | 全部事件 |
| 讓角標、狀態等同步讀取的值保持最新 | 用事件讀取同步狀態的值 |
| 判斷錯誤、查錯誤碼 | 錯誤物件、SDK 自己的錯誤碼、常見的服務端錯誤碼 |
| 給使用者顯示錯誤提示 | 顯示錯誤提示 |
| 瞭解 SDK 自動重試了什麼 | 離線與重試 |
訂閱與取消
const off = im.on('message.received', ({ message, alert }) => {
if (alert) showToast(`${message.sender}:新消息`);
});
// 不再需要时取消
off();
// 只处理一次
im.once('sync.completed', ({ trigger }) => console.log('第一次同步完成', trigger));im.on(event, listener)返回取消訂閱的函式,可以重複呼叫;im.once只觸發一次。- 事件名和載荷都有型別:
listener的引數型別由事件名決定(DREvents[事件名])。 - 監聽函式丟擲的異常被記為
warn日誌,不影響其他監聽函式,也不影響 SDK。 - 資料變化的事件在本地資料更新之後發出,載荷只說明變了什麼(如哪些會話變了),你從對應的列表或方法讀取最新的資料。
- 同一個變化只發出一次:本人操作的結果和隨後服務端的通知會合並,不會收到重複的事件。
- 同一瀏覽器的每個標籤頁都會收到同樣的事件。
im.destroy()之後不再發出任何事件。
在 React、Vue 中訂閱事件,可以用繫結包的 useDREvent,元件解除安裝時自動取消,見在 React 和 Vue 中使用。
全部事件
登入與連線
| 事件 | 載荷 | 說明 |
|---|---|---|
auth.stateChanged | AuthState | 登入狀態變化:登入、退出、會話結束(帶原因)、服務暫停與恢復,見會話結束 |
auth.userSwitched | { username: string } | 其他標籤頁登入了另一個使用者,本標籤頁已切換到新使用者。開啟著的列表已被清空並釋放,請按新使用者重新載入介面 |
connection.stateChanged | ConnectionState | 連線狀態變化,見連線狀態 |
sdk.upgradeRequired | { min_version: string } | SDK 版本低於服務端要求的最低版本,連線已停止,本地資料只讀。請提示使用者重新整理頁面或升級 |
tabs.roleChanged | { isLeader: boolean; isAlertTab: boolean } | 本標籤頁成為或不再是主標籤頁、負責提醒的標籤頁 |
tabs.refreshRequired | { reason: 'protocol_version' | 'storage_version' } | 同一瀏覽器中打開了新版本的頁面,或本地資料被新版本升級,本頁面只能讀取本地資料,請提示使用者重新整理 |
同步與本地資料
| 事件 | 載荷 | 說明 |
|---|---|---|
sync.completed | { modules: SyncModule[]; trigger: string } | 一輪同步完成。modules 為這一輪同步的模組(config、me、friends、groups、messages、push、calls、chatrooms、presence);trigger 為同步的起因:login(登入後)、reconnect(重連後)、sync_required(服務端要求全量同步)、hint(服務端提示有新資料)、foreground(頁面回到前臺)、periodic(定期檢查)、fallback(長連線不可用時的定期同步) |
sync.failed | { module: SyncModule; error: DRError } | 某個模組同步失敗,SDK 會自動重試,一般只需記錄日誌 |
storage.reset | { reason: 'reset_required' | 'reloaded'; dropped_messages?: number } | 本地資料已重置(服務端要求)或已從本地儲存重新載入。開啟著的列表已自動重新讀取,你只需重新讀取自己另外儲存的資料;dropped_messages 為因此丟棄的未發出訊息數 |
storage.modeChanged | { mode: 'indexeddb' | 'memory'; reason: 'unavailable' | 'quota_exceeded' | 'upgrade_blocked' } | 本地資料改為只儲存在記憶體中:瀏覽器不允許使用 IndexedDB、磁碟空間不足、或舊版本的頁面阻止了升級。功能照常,重新整理頁面後要從服務端重新載入 |
執行配置與本人
| 事件 | 載荷 | 說明 |
|---|---|---|
config.changed | ClientConfig | null | 應用的執行配置變化,與 im.config 相同;退出後為 null |
me.changed | SelfProfile | null | 本人資料變化,與 im.users.me() 相同;退出後為 null |
me.muteChanged | { scope: 'chat' | 'group' | 'room'; muted: boolean; expires_at: string | null } | 本人被全域性禁言或解除禁言(本次連線期間收到的) |
users.changed | { usernames: string[] } | 其他使用者的資料快取更新,用 im.users.get() 顯示的介面應重新讀取 |
devices.changed | { devices: OnlineDevice[] } | 本人的線上裝置變化,與 im.devices.online() 相同 |
devices.newLogin | { session_id: string; device_name: string; platform: string; login_method: string; created_at: string } | 本人在一臺新裝置上登入,可以提示“你的賬號在 XX 上登入” |
會話與訊息
| 事件 | 載荷 | 說明 |
|---|---|---|
conversations.changed | { upserted: string[]; removed: string[] } | 會話列表中的會話新增、變化或移除,值為 conversation_key |
conversations.unreadChanged | { total: number; source: 'local' | 'server' } | 未讀總數變化,total 與 im.conversations.getUnreadTotal() 相同 |
messages.changed | { conversation_key: string; upserted: number[]; removed: number[]; pending: string[]; renamed_from?: string } | 某個會話的訊息變化:upserted、removed 為訊息的序號,pending 為傳送佇列中變化的 client_msg_id;renamed_from 表示這個會話由草稿會話變為正式會話,值為原來的草稿鍵 |
message.received | { message: MessageView; notify: NotifyDecision | null; alert: boolean } | 收到別人發來的新訊息,用於提醒:notify 為是否應該提醒(已考慮免打擾、勿擾時段等),alert 為 true 表示本標籤頁負責提醒。只在即時收到時發出,補齊的歷史訊息、重連後同步得到的離線期間的訊息不發出 |
message.sendFailed | { client_msg_id: string; conversation_key: string; error: DRError } | 一條訊息最終傳送失敗(自動重試已用完,或被服務端拒絕)。訊息留在列表中,狀態為 failed,可以讓使用者重發或刪除 |
message.online | { message: OnlineMessage } | 收到只推線上的訊息(sendOnline 發出的,如“對方正在操作”的自定義信令),不儲存 |
typing.changed | { conversation_key: string; usernames: string[] } | 會話中正在輸入的人變化 |
receipts.changed | { conversation_id: string; seqs: number[] } | 群訊息的已讀人數變化,用 im.messages.getReceipt() 讀取 |
聯絡人與群組
| 事件 | 載荷 | 說明 |
|---|---|---|
friends.changed | { upserted: string[]; removed: string[] } | 好友新增、資料或備註變化、刪除,值為使用者名稱 |
blacklist.changed | { upserted: string[]; removed: string[] } | 黑名單變化 |
friendRequests.changed | { lists: Array<'received' | 'sent'>; unread_count: number } | 收到的或發出的好友申請變化,unread_count 為未讀的收到的申請數 |
groups.changed | { upserted: string[]; removed: string[] } | 我的群列表或群資訊變化,值為群 ID |
groupMembers.changed | { group_id: string; usernames: string[] | null } | 群成員變化;usernames 為 null 表示整個成員列表變化 |
groupRequests.changed | { list: 'pending' | 'invitations' | 'applications'; group_id: string | null } | 入群請求變化:pending 為某個群待審批的請求(帶 group_id),invitations 為本人收到的入群邀請,applications 為本人的入群申請 |
推送設定與線上狀態
| 事件 | 載荷 | 說明 |
|---|---|---|
push.changed | { settings: boolean; mutes: Array<{ conversation_type: string; target: string }> } | 推送設定(settings 為 true)或會話免打擾變化 |
presence.changed | { items: PresenceState[]; reset: boolean; cleared?: string[] } | 訂閱的人線上狀態變化;reset 為 true 表示本地的線上狀態已全部清除(如重新連線後),cleared 為被清除了狀態的人 |
presence.subscribeFailed | { usernames: string[]; reason: 'denied' | 'limit_exceeded' | 'presence_disabled' } | 訂閱沒有生效的人:沒有許可權檢視、超出訂閱上限、應用沒有開啟線上狀態 |
音影片
| 事件 | 載荷 | 說明 |
|---|---|---|
call.incoming | { call: CallHandle; alert: boolean } | 來電。alert 為 true 時本標籤頁負責振鈴和顯示來電介面 |
call.changed | { call: CallHandle; change: CallChange | null } | 通話的狀態、成員等變化;change 為 null 表示由本標籤頁自己的操作或重新同步引起 |
groupCall.changed | GroupCallBanner | null | 群中正在進行的通話變化,用於顯示“群通話進行中”的橫幅(group_id、call_id、media、status、joined_count、initiator、version);為 null 表示某個群的橫幅已移除,請用 im.calls.groupCallBanner(group_id) 重新讀取各群的橫幅 |
通話的詳細用法見音視訊通話。聊天室的訊息、成員進出等在進入聊天室得到的物件上訂閱,見聊天室。遊戲房間的事件見遊戲房間事件。
用事件讀取同步狀態的值
以下值可以同步讀取,變化時發出對應的事件,“訂閱事件 + 讀取”就能讓介面保持最新:
| 讀取 | 變化時的事件 |
|---|---|
im.auth.state、im.auth.currentUser | auth.stateChanged |
im.connection.state | connection.stateChanged |
im.connection.isLeader、im.connection.isAlertTab | tabs.roleChanged |
im.config | config.changed |
im.users.me() | me.changed |
im.users.myMute | me.muteChanged |
im.users.get(username) | users.changed |
im.conversations.getUnreadTotal() | conversations.unreadChanged |
im.conversations.getTyping(conversation_key) | typing.changed |
im.friends.get(username)、im.friends.listInfo | friends.changed |
im.friends.blacklist.has(username) | blacklist.changed |
im.friends.requests.unreadCount | friendRequests.changed |
im.messages.getReceipt(conversation_id, seq) | receipts.changed |
im.push.settings()、im.push.getMute(target) | push.changed |
im.presence.get(username) | presence.changed |
im.devices.online() | devices.changed |
im.calls.current、im.calls.incoming | call.incoming、call.changed |
im.calls.groupCallBanner(group_id) | groupCall.changed |
值沒有變化時,讀取返回同一個物件。登入、退出、切換使用者、本地資料重新載入時,這些值也可能變化,對應的事件同樣會發出。
const showUnread = () => render(im.conversations.getUnreadTotal());
im.on('conversations.unreadChanged', showUnread);
showUnread();錯誤物件
SDK 的所有錯誤都是 DRError:返回 Promise 的方法以它拒絕,同步方法以它丟擲,message.sendFailed、sync.failed 等事件的載荷中也是它。
import { DRError } from '@deeprespond/im-web';
try {
await im.groups.leave('g_123');
} catch (err) {
if (!(err instanceof DRError)) throw err;
console.log(err.code, err.reason, err.details, err.status, err.requestId, err.retryAfter, err.source);
}| 欄位 | 型別 | 說明 |
|---|---|---|
code | string | 錯誤碼:服務端返回的錯誤碼,或 SDK 自己的錯誤碼(見下文) |
reason | string | undefined | 原因,即 details.reason |
details | Record<string, unknown> | undefined | 服務端返回的 details,原樣;SDK 自己的錯誤中為補充資訊 |
status | number | undefined | HTTP 狀態碼;長連線的錯誤和 SDK 自己的錯誤沒有 |
requestId | string | undefined | 服務端的 request_id,聯絡技術支援時提供 |
retryAfter | number | undefined | 建議的等待時間,單位為秒 |
source | 'http' | 'ws' | 'local' | 錯誤的來源:HTTP 請求、長連線、SDK 本地 |
message | string | 除錯用的說明,不要直接顯示給使用者,提示文字見顯示錯誤提示 |
請按 code 和 reason 判斷錯誤,不要按 status 或 message 判斷。
與服務端錯誤碼的關係
服務端返回的錯誤原樣交給你,code、details 與服務端文件相同,source 為 http 或 ws。各錯誤碼的含義和 details 的取值見服務端的錯誤碼,客戶端特有的錯誤碼(如 user_muted、group_muted、not_friend、user_blocked)見其中的控制台和客戶端介面的錯誤碼。
SDK 在發出請求之前先在本地檢查,確定會被服務端拒絕的直接拒絕,source 為 local:
- 功能沒有開啟、沒有許可權的(如應用沒有開啟群已讀回執、普通成員 @所有人),沿用服務端的
permission_denied和原因,如read_ack_disabled、mention_all_denied、presence_disabled; - 超出服務端的固定頻率限制的(如“全部已讀”每分鐘 2 次),沿用
rate_limited,帶retryAfter; - 引數和內容不合規的(大小、格式、必填欄位、不支援的字元等),一律為
local_validation,details.reason和details.field說明原因。local_validation總是表示請求沒有發出。
這樣你對“功能不可用、沒有許可權”和“太頻繁”只需按服務端的錯誤碼處理一次。
SDK 自己的錯誤碼
code | 含義 | 建議 |
|---|---|---|
network_error | 網路不可用或請求沒有送達 | 提示檢查網路,稍後重試 |
timeout | 請求超時 | 稍後重試;寫操作先確認結果,見離線與重試 |
aborted | 被你用 AbortSignal 取消 | 不提示 |
not_signed_in | 未登入時呼叫了需要登入的方法 | 先登入 |
not_connected | 必須走長連線的操作(如聊天室的部分操作)在未連線時呼叫 | 等連線就緒後再試 |
leader_unavailable | 同一瀏覽器的主標籤頁正在切換,呼叫沒有完成 | 稍後重試,見多個標籤頁 |
local_validation | 本地檢查不通過,請求沒有發出。details.reason 為原因(如 required、too_large、control_characters、url_not_allowed),details.field 為欄位 | 提示使用者修改 |
storage_error | 讀寫本地儲存出錯 | 提示重新整理頁面 |
unsupported | 瀏覽器不滿足執行環境要求,或服務端沒有提供所需的服務(如沒有開通檔案服務時上傳檔案,details.reason 為 media_disabled) | 提示更換瀏覽器,或隱藏對應的功能 |
permission_required | 使用者沒有授權使用麥克風或攝像頭,details.permissions 列出缺少的許可權 | 引導使用者在瀏覽器中授權 |
device_error | 麥克風或攝像頭不存在或被佔用,details.device 為 microphone 或 camera,details.reason 為 not_found 或 busy | 提示檢查裝置 |
invalid_state | 當前狀態下不能呼叫,details.reason 說明原因:client_exists(這個頁面已有同一個 AppKey 的客戶端)、destroyed(客戶端已釋放)、disposed(列表已釋放)、signed_in(不能清除當前使用者的本地資料)、upgrade_required(SDK 版本過低,本地資料只讀)等 | 一般是呼叫順序的問題,檢查程式碼 |
send_abandoned | SDK 放棄傳送一條訊息:details.reason 為 attachment_lost(附件已丟失,如頁面關閉後超過 50 MB 的附件)或 expired(超過 48 小時沒有發出) | 提示使用者重新發送 |
local_validation 的原因
local_validation 的 details.reason 說明哪裡不合規,details.field 為欄位名(如 body.text、username):
details.reason | 含義 |
|---|---|
required | 必填的引數或欄位為空 |
invalid_format | 格式不對,如 appKey、apiUrl、client_msg_id |
invalid_value | 取值不在允許的範圍內 |
invalid_type | 引數的型別不對 |
out_of_range | 數值超出範圍 |
too_long | 文字太長 |
too_large | 內容或檔案太大,如訊息超過執行配置的 max_message_body_bytes、附件超過 max_upload_bytes |
too_many_items | 一次傳入的專案太多,如一次刪除超過 100 條訊息 |
control_characters | 文字中有不支援的控制字元(只有文本訊息的正文允許換行、回車和製表符) |
invalid_body、unknown_type | 訊息內容不符合訊息型別的要求;不支援的訊息型別 |
mentions_not_allowed、receipt_not_allowed | @ 提及、群已讀回執只能用於群聊 |
url_not_allowed | 應用開啟了只接受本服務的檔案地址,這個地址不符合要求 |
invalid_purpose | 這種檔案不能用於這裡(如用影片作頭像) |
invalid_ext、invalid_priority、invalid_attribute_value、attributes_too_large | 聊天室的擴充套件資訊、訊息優先順序、屬性不符合要求 |
too_many_invitees | 一次邀請通話的人太多 |
invalid_evidence、self_report | 舉報的證據訊息不符合要求;不能舉報自己 |
not_found | 本地找不到要操作的會話或訊息(如重發一條已不在傳送佇列中的訊息) |
describeError 對其中常見的原因給出了專門的提示,其餘顯示“內容不符合要求”。
常見的服務端錯誤碼
code | 含義 | 建議 |
|---|---|---|
invalid_argument | 引數不符合服務端的規則 | 提示使用者修改;details.reason 說明原因 |
unauthenticated、session_revoked | 登入失效 | SDK 已自動處理(續期或結束會話),你只需處理 auth.stateChanged 中的 ended |
invalid_credentials | 使用者名稱、密碼或憑證錯誤 | 見登入失敗 |
permission_denied | 沒有許可權,或功能沒有開啟,details.reason 說明原因 | 按原因提示,或隱藏對應的功能 |
not_found | 使用者、群、會話、訊息等不存在或已刪除 | 提示“內容不存在或已刪除” |
already_exists | 要建立的已存在 | 視為成功或提示 |
version_conflict | 資料已被修改 | 重新讀取後再提交 |
limit_exceeded | 超出數量上限,details.reason 說明是哪一項 | 提示已達上限 |
payload_too_large | 內容或檔案太大 | 提示使用者縮短內容或換小一些的檔案 |
rate_limited | 操作太頻繁 | 按 retryAfter 稍後再試;SDK 已對可以安全重試的請求自動等待重試 |
too_many_attempts | 密碼錯誤次數過多 | 按 retryAfter 提示稍後再試 |
message_rejected、content_rejected | 訊息或資料沒有通過內容安全檢查 | 提示使用者修改內容;reason 為 app_rejected 時,message 是你的服務端給出的提示,可以直接顯示 |
user_muted、group_muted | 本人被全域性禁言、在群中被禁言或群開啟了全員禁言 | 提示禁言,details.expires_at 為到期時間 |
user_blocked | 被對方拉黑 | 提示“對方拒收了你的訊息” |
not_friend | 應用要求只能給好友發訊息,雙方不是好友 | 提示先加好友 |
not_group_member | 本人已不在群中 | 提示並重新整理介面 |
tenant_unavailable、app_unavailable | 服務暫停或只讀 | 提示“服務暫時不可用”,見服務暫停 |
internal | 服務端故障 | 稍後重試,持續出現時帶上 requestId 聯絡技術支援 |
顯示錯誤提示
@deeprespond/im-web/locale/zh-CN 中的 describeError 按 code 和 reason 給出中文的提示文字,如“傳送太頻繁,請稍後再試”“群主已開啟全員禁言”“你已被禁言,至 10 月 5 日 18:00”:
import { DRError } from '@deeprespond/im-web';
import { describeError } from '@deeprespond/im-web/locale/zh-CN';
im.on('message.sendFailed', ({ error }) => showToast(describeError(error)));
try {
await im.friends.requests.send({ username: 'lisi', message: '你好' });
} catch (err) {
if (err instanceof DRError) showToast(describeError(err));
}查詢順序為先找 code.reason(如 permission_denied.mention_all_denied),再找 code,都沒有時顯示通用的“伺服器繁忙,請稍後重試”。例外:message_rejected、permission_denied 的原因為 app_rejected 時,顯示服務端返回的 message(你的服務端給出的提示)。
要修改部分文案,或換成其他語言,傳入第二個引數;文案表 zhCN.errors 的鍵就是上面說的 code 或 code.reason:
import { describeError, zhCN } from '@deeprespond/im-web/locale/zh-CN';
import type { DRError } from '@deeprespond/im-web';
const myLocale = {
errors: {
rate_limited: '手速太快啦,休息一下',
'permission_denied.mention_all_denied': '只有管理员可以 @所有人',
},
};
const tip = (err: DRError) => describeError(err, myLocale);
console.log(Object.keys(zhCN.errors)); // 内置的全部条目離線與重試
SDK 按錯誤的型別自動處理,你只需處理最終返回的錯誤:
| 類別 | 錯誤碼 | SDK 的處理 |
|---|---|---|
| 登入失效 | unauthenticated、session_revoked | 令牌過期的自動續期並重發一次請求;會話被吊銷的結束會話,見會話結束 |
| 服務暫停或只讀 | tenant_unavailable、app_unavailable | 返回給你;確認是服務暫停的,進入服務暫停狀態,恢復後自動繼續 |
| 限流 | rate_limited、too_many_attempts | 等待時間不超過 60 秒的,等待後自動重試;更長的返回給你。傳送好友申請、建群、邀請入群、申請入群、發起和邀請通話、舉報、聊天室發訊息,以及 too_many_attempts,不自動重試 |
| 暫時故障 | network_error、timeout、internal、HTTP 5xx | 可以安全重發的請求(查詢、帶冪等鍵的寫操作、本身冪等的操作如標記已讀)按退避自動重試,最多 3 次;其他寫操作不自動重試,返回給你 |
| 需要使用者處理 | 其餘錯誤碼 | 返回給你,按 code 和 details 提示 |
訊息的傳送另有傳送佇列:
im.messages.send()把訊息寫入傳送佇列後就返回,之後由 SDK 傳送。斷網時訊息在佇列中等待,網路恢復後自動發出;頁面關閉後,下次開啟時繼續傳送。- 傳送遇到網路錯誤、超時、服務端故障時,按 1、2、4、8、16、30 秒的間隔重試,網路可用的時間累計 2 分鐘仍未成功的標為失敗;被限流的按服務端給出的時間等待後重試。
- 被服務端拒絕(如被禁言、被拉黑、內容未通過稽核)的立即標為失敗。
- 失敗時訊息狀態變為
failed,併發出message.sendFailed。可以呼叫im.messages.resend(client_msg_id)重發,或im.messages.discard(client_msg_id)刪除,見訊息。 - 同一條訊息重試時使用同一個
client_msg_id,服務端據此去重,不會發出兩條。
沒有自動重試的寫操作(如建群、傳送好友申請、修改群資料)遇到 network_error、timeout 時,請求可能已經執行。請先查詢結果(如重新讀取群列表),確認沒有生效再讓使用者重試。
離線時:本地資料照常可讀,介面可以繼續顯示;會話和訊息的操作中只修改本地的(如草稿)立即生效,需要請求服務端的在自動重試後返回 network_error,傳送訊息進入傳送佇列。連線狀態為 offline 或 waiting,網路恢復後 SDK 自動重連並同步離線期間的變化。
介面參考
im.on()
訂閱事件。
| 引數 | 型別 | 必填 | 說明 |
|---|---|---|---|
event | keyof DREvents | 是 | 事件名,見全部事件 |
listener | (payload: DREvents[E]) => void | 是 | 監聽函式,引數為事件的載荷 |
返回值:() => void,取消訂閱的函式,可以重複呼叫。客戶端已釋放時返回的函式什麼也不做。
im.once()
訂閱事件,只觸發一次。引數和返回值與 im.on() 相同;在觸發前呼叫返回的函式可以取消。
describeError()
返回錯誤的提示文字(string)。推薦從 @deeprespond/im-web/locale 匯入,第二個引數為語言:
| 呼叫 | 語言 |
|---|---|
describeError(err) | 簡體中文(預設) |
describeError(err, 'zh-TW') | 繁體中文 |
describeError(err, 'en') | 英語 |
提示文字按 code 和 reason 選擇;你的服務端在回撥中給出的拒絕提示原樣顯示。要修改部分文案,用 createLocale(language) 取得一份獨立的文案表,修改後交給需要文案表的顯示輔助函式。
上文示例用的 @deeprespond/im-web/locale/zh-CN 是舊的入口,仍然可用。它的 describeError(err, locale) 第二個引數是文案表物件,不是語言名,兩個入口的寫法不要混用。完整示例見SDK 多語言。
資料結構
DRError
繼承自 Error,欄位見錯誤物件。另有 name,固定為 'DRError'。
DREvents
事件名到載荷型別的對映,im.on() 和 im.once() 據此推斷載荷的型別,各事件的載荷見全部事件。可以用它宣告自己的事件處理函式:
import type { DREvents } from '@deeprespond/im-web';
function onReceived(p: DREvents['message.received']) {
console.log(p.message.conversation_id, p.alert);
}
im.on('message.received', onReceived);NotifyDecision
message.received 的 notify,說明這條訊息是否應該提醒。
| 欄位 | 型別 | 說明 |
|---|---|---|
notify | boolean | 是否應該提醒 |
title | string | 通知的標題,按推送設定的預覽方式生成,可選 |
body | string | 通知的內容,可選 |
reason | string | 不提醒的原因,可選:dnd(勿擾中)、quiet_hours(勿擾時段)、muted(會話免打擾)、not_mentioned(免打擾為只在 @ 本人時提醒,而這條沒有 @ 本人)、excluded(訊息不計未讀)、self(本人發的)、tip(群提示)、call(通話記錄)、not_loaded(推送設定還沒有載入) |
提醒的完整用法見提醒、推送設定與舉報。
頻道事件
本標籤頁的當前頻道變化時發出 channel.changed,載荷為 { channel: ChannelHandle | null }:加入頻道後為頻道的控制代碼,離開後為 null。
- 這個事件只在本標籤頁發出,其他標籤頁收不到,也拿不到這個控制代碼。請在加入頻道、播放音影片的頁面中處理。
- 軌道、成員、離開、關閉和連線的事件在
ChannelHandle上訂閱,完整的表見頻道事件。 - 因許可權失效或心跳失敗離開頻道後,SDK 不會自動重新加入。
遊戲房間事件
加入遊戲房間、當前房間結束時發出 game.changed,載荷為 { room: GameRoom | null }:加入後為房間物件,房間對本客戶端結束(離開、被移出、對局結束、超過重連視窗)後為 null。
im.on('game.changed', ({ room }) => {
if (room) showMatchScreen(room.roomId);
else showLobby();
});- 這個事件只在本客戶端發出,同一瀏覽器的其他標籤頁收不到。
- 幀、成員進出、房間狀態、自定義訊息和結束原因在
GameRoom物件上訂閱(room.onFrame()、room.onMember()、room.onClose()等),見遊戲房間 · Web 客戶端接入。 - 斷線重連由 SDK 自動處理,重連期間不會發出
game.changed;房間物件的state變為reconnecting或rejoining,可以用room.onState()訂閱。
簡體、繁體與英語提示
SDK 自帶簡體中文、繁體中文和英語的提示文字,預設簡體中文,不呼叫線上翻譯:
| 平臺 | 用法 |
|---|---|
| Web | @deeprespond/im-web/locale 的 createLocale()、describeError() |
| Android | DRLocale.en、DRLocale.zhTW、DRLocale.forLanguage(tag) |
| Flutter | 從 render.dart 匯入 en、zhTW、localeForLanguage(tag) |
把選好的文案表交給顯示輔助函式即可,使用者選擇的語言由你的應用儲存。切換語言只改變提示文字,錯誤碼和使用者發的內容不變。
服務端的錯誤可能帶 message_key 和 message_params(用於生成本地化的提示),判斷錯誤時仍然用 code、reason 和 details。詳細的入口和語言的選擇規則見語言與本地化。
