tim-js-sdk 登錄、接收信息、發(fā)送消息

簡(jiǎn)介

本文主要介紹如何快速地將騰訊云 IM SDK 集成到您的 Web 項(xiàng)目中。
騰訊云即時(shí)通信IM SDK API 文檔
示例demo下載

tim-js-sdk 功能擴(kuò)展 (好友接口)

準(zhǔn)備工作

  1. 在騰訊云官網(wǎng)上創(chuàng)建應(yīng)用,獲取到相應(yīng)的SDKAppID和相應(yīng)的秘鑰信息
  2. 安裝sdk

集成 SDK

// IM Web SDK
// 從v2.11.2起,SDK 支持了 WebSocket,推薦接入;v2.10.2及以下版本,使用 HTTP
npm install tim-js-sdk --save
// 發(fā)送圖片、文件等消息需要騰訊云即時(shí)通信 IM 上傳插件
npm install tim-upload-plugin --save

在項(xiàng)目腳本里引入模塊。

// 從v2.11.2起,SDK 支持了 WebSocket,推薦接入;v2.10.2及以下版本,使用 HTTP
import TIM from 'tim-js-sdk';
import TIMUploadPlugin from 'tim-upload-plugin';
let options = {
 SDKAppID: xxxxxxxx // 接入時(shí)需要將0替換為您的即時(shí)通信 IM 應(yīng)用的 SDKAppID
};
// 創(chuàng)建 SDK 實(shí)例,`TIM.create()`方法對(duì)于同一個(gè) `SDKAppID` 只會(huì)返回同一份實(shí)例
let tim = TIM.create(options); // SDK 實(shí)例通常用 tim 表示
// 設(shè)置 SDK 日志輸出級(jí)別,詳細(xì)分級(jí)請(qǐng)參見(jiàn) <a >setLogLevel 接口的說(shuō)明</a>
tim.setLogLevel(0); // 普通級(jí)別,日志量較多,接入時(shí)建議使用
// tim.setLogLevel(1); // release 級(jí)別,SDK 輸出關(guān)鍵信息,生產(chǎn)環(huán)境時(shí)建議使用
// 注冊(cè)騰訊云即時(shí)通信 IM 上傳插件
tim.registerPlugin({'tim-upload-plugin': TIMUploadPlugin});

初始化與登錄(Web)

1. 創(chuàng)建 SDK 實(shí)例
請(qǐng)參考上面的集成SDK方法

2. 事件綁定

// 監(jiān)聽(tīng)事件,例如:
tim.on(TIM.EVENT.SDK_READY, function(event) {
// 收到離線消息和會(huì)話列表同步完畢通知,接入側(cè)可以調(diào)用 sendMessage 等需要鑒權(quán)的接口
// event.name - TIM.EVENT.SDK_READY
});
tim.on(TIM.EVENT.MESSAGE_RECEIVED, function(event) {
// 收到推送的單聊、群聊、群提示、群系統(tǒng)通知的新消息,可通過(guò)遍歷 event.data 獲取消息列表數(shù)據(jù)并渲染到頁(yè)面
// event.name - TIM.EVENT.MESSAGE_RECEIVED
// event.data - 存儲(chǔ) Message 對(duì)象的數(shù)組 - [Message]
});
tim.on(TIM.EVENT.MESSAGE_REVOKED, function(event) {
// 收到消息被撤回的通知
// event.name - TIM.EVENT.MESSAGE_REVOKED
// event.data - 存儲(chǔ) Message 對(duì)象的數(shù)組 - [Message] - 每個(gè) Message 對(duì)象的 isRevoked 屬性值為 true
});
tim.on(TIM.EVENT.MESSAGE_READ_BY_PEER, function(event) {
// SDK 收到對(duì)端已讀消息的通知,即已讀回執(zhí)。使用前需要將 SDK 版本升級(jí)至 v2.7.0 或以上。僅支持單聊會(huì)話。
// event.name - TIM.EVENT.MESSAGE_READ_BY_PEER
// event.data - event.data - 存儲(chǔ) Message 對(duì)象的數(shù)組 - [Message] - 每個(gè) Message 對(duì)象的 isPeerRead 屬性值為 true
});
tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, function(event) {
// 收到會(huì)話列表更新通知,可通過(guò)遍歷 event.data 獲取會(huì)話列表數(shù)據(jù)并渲染到頁(yè)面
// event.name - TIM.EVENT.CONVERSATION_LIST_UPDATED
// event.data - 存儲(chǔ) Conversation 對(duì)象的數(shù)組 - [Conversation]
});
tim.on(TIM.EVENT.GROUP_LIST_UPDATED, function(event) {
// 收到群組列表更新通知,可通過(guò)遍歷 event.data 獲取群組列表數(shù)據(jù)并渲染到頁(yè)面
// event.name - TIM.EVENT.GROUP_LIST_UPDATED
// event.data - 存儲(chǔ) Group 對(duì)象的數(shù)組 - [Group]
});
tim.on(TIM.EVENT.PROFILE_UPDATED, function(event) {
// 收到自己或好友的資料變更通知
// event.name - TIM.EVENT.PROFILE_UPDATED
// event.data - 存儲(chǔ) Profile 對(duì)象的數(shù)組 - [Profile]
});
tim.on(TIM.EVENT.BLACKLIST_UPDATED, function(event) {
// 收到黑名單列表更新通知
// event.name - TIM.EVENT.BLACKLIST_UPDATED
// event.data - 存儲(chǔ) userID 的數(shù)組 - [userID]
});
tim.on(TIM.EVENT.ERROR, function(event) {
// 收到 SDK 發(fā)生錯(cuò)誤通知,可以獲取錯(cuò)誤碼和錯(cuò)誤信息
// event.name - TIM.EVENT.ERROR
// event.data.code - 錯(cuò)誤碼
// event.data.message - 錯(cuò)誤信息
});
tim.on(TIM.EVENT.SDK_NOT_READY, function(event) {
// 收到 SDK 進(jìn)入 not ready 狀態(tài)通知,此時(shí) SDK 無(wú)法正常工作
// event.name - TIM.EVENT.SDK_NOT_READY
});
tim.on(TIM.EVENT.KICKED_OUT, function(event) {
// 收到被踢下線通知
// event.name - TIM.EVENT.KICKED_OUT
// event.data.type - 被踢下線的原因,例如:
//    - TIM.TYPES.KICKED_OUT_MULT_ACCOUNT 多實(shí)例登錄被踢
//    - TIM.TYPES.KICKED_OUT_MULT_DEVICE 多終端登錄被踢
//    - TIM.TYPES.KICKED_OUT_USERSIG_EXPIRED 簽名過(guò)期被踢 (v2.4.0起支持)。 
});
tim.on(TIM.EVENT.NET_STATE_CHANGE, function(event) { 
//  網(wǎng)絡(luò)狀態(tài)發(fā)生改變(v2.5.0 起支持)。 
// event.name - TIM.EVENT.NET_STATE_CHANGE 
// event.data.state 當(dāng)前網(wǎng)絡(luò)狀態(tài),枚舉值及說(shuō)明如下: 
//     \- TIM.TYPES.NET_STATE_CONNECTED - 已接入網(wǎng)絡(luò) 
//     \- TIM.TYPES.NET_STATE_CONNECTING - 連接中。很可能遇到網(wǎng)絡(luò)抖動(dòng),SDK 在重試。接入側(cè)可根據(jù)此狀態(tài)提示“當(dāng)前網(wǎng)絡(luò)不穩(wěn)定”或“連接中” 
//    \- TIM.TYPES.NET_STATE_DISCONNECTED - 未接入網(wǎng)絡(luò)。接入側(cè)可根據(jù)此狀態(tài)提示“當(dāng)前網(wǎng)絡(luò)不可用”。SDK 仍會(huì)繼續(xù)重試,若用戶網(wǎng)絡(luò)恢復(fù),SDK 會(huì)自動(dòng)同步消息  
});
// 開(kāi)始登錄 
tim.login({userID: 'your userID', userSig: 'your userSig'});

3. 登錄

用戶登錄 IM SDK 才能正常收發(fā)消息,登錄需要用戶提供 UserID、UserSig 等信息,具體含義請(qǐng)參見(jiàn) 登錄鑒權(quán)。登錄成功后,需要先等 SDK 處于 ready 狀態(tài)才能調(diào)用 sendMessage 等需要鑒權(quán)的接口,您可以通過(guò)監(jiān)聽(tīng)事件 TIM.EVENT.SDK_READY 獲取 SDK 狀態(tài)。

// userID [String] 用戶 ID。
// userSig [String] 用戶登錄即時(shí)通信 IM 的密碼,其本質(zhì)是對(duì) UserID 等信息加密后得到的密文。具體生成方法請(qǐng)參見(jiàn) 生成 UserSig。
tim.login({userID: xxx, userSig: xxx});

返回值

該接口返回 Promise 對(duì)象。

tim.login({userID: 'your userID', userSig: 'your userSig'})
    .then(function(imResponse) {
        console.log(imResponse.data); // 登錄成功
        if (imResponse.data.repeatLogin === true) {
          // 標(biāo)識(shí)賬號(hào)已登錄,本次登錄操作為重復(fù)登錄。v2.5.1 起支持
          console.log(imResponse.data.errorInfo);
        }
    }).catch(function(imError) {
        console.warn('login error:', imError); // 登錄失敗的相關(guān)信息
    });

4. 登出

// then的回調(diào)函數(shù)參數(shù)為 IMResponse,IMResponse.data為空對(duì)象。表示成功登出
tim.logout().then(function(imResponse) {
        console.log(imResponse.data); // 登出成功
    }).catch(function(imError) {
        console.warn('logout error:', imError);
    });

消息收發(fā)(Web)

一. 發(fā)送消息

發(fā)送消息需先創(chuàng)建消息內(nèi)容對(duì)象, 再通過(guò)發(fā)送消息接口發(fā)送消息給指定用戶或群組

1. 創(chuàng)建文本消息

tim.createTextMessage({
    // [String] 消息接收方的 userID 或 groupID
    to,
    // [String] 會(huì)話類(lèi)型,取值TIM.TYPES.CONV_C2C(端到端會(huì)話)或TIM.TYPES.CONV_GROUP(群組會(huì)話)
    conversationType,
    // [String] 消息優(yōu)先級(jí)(默認(rèn)值: TIM.TYPES.MSG_PRIORITY_NORMAL)
    priority,
    // [Object] 消息內(nèi)容的容器
    payload
})

payload 內(nèi)容格式如下:

Name Type Description
text String 消息文本內(nèi)容

示例

// 發(fā)送文本消息,Web 端與小程序端相同
// 1. 創(chuàng)建消息實(shí)例,接口返回的實(shí)例可以上屏
let message = tim.createTextMessage({
    to: 'user1',
    conversationType: TIM.TYPES.CONV_C2C,
    // 消息優(yōu)先級(jí),用于群聊(v2.4.2起支持)。如果某個(gè)群的消息超過(guò)了頻率限制,后臺(tái)會(huì)優(yōu)先下發(fā)高優(yōu)先級(jí)的消息,詳細(xì)請(qǐng)參考:https://cloud.tencent.com/document/product/269/3663#.E6.B6.88.E6.81.AF.E4.BC.98.E5.85.88.E7.BA.A7.E4.B8.8E.E9.A2.91.E7.8E.87.E6.8E.A7.E5.88.B6)
    // 支持的枚舉值:TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL(默認(rèn)), TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST
    // priority: TIM.TYPES.MSG_PRIORITY_NORMAL,
    payload: {
      text: 'Hello world!'
    }
});
// 2. 發(fā)送消息
tim.sendMessage(message).then(function(imResponse) {
    // 發(fā)送成功
    console.log(imResponse);
}).catch(function(imError) {
    // 發(fā)送失敗
    console.warn('sendMessage error:', imError);
});

2. 創(chuàng)建圖片消息

tim.createImageMessage({
    // [String] 消息接收方的 userID 或 groupID
    to,
    // [String] 會(huì)話類(lèi)型,取值TIM.TYPES.CONV_C2C(端到端會(huì)話)或TIM.TYPES.CONV_GROUP(群組會(huì)話)
    conversationType,
    // [String] 消息優(yōu)先級(jí)(默認(rèn)值: TIM.TYPES.MSG_PRIORITY_NORMAL)
    priority,
    // [Object] 消息內(nèi)容的容器
    payload
    // [function] 獲取上傳進(jìn)度的回調(diào)函數(shù)
    onProgress
})

payload 內(nèi)容格式如下:
| Name | Type | Description |
|--|--|-|--
| text | HTMLInputElement | Object| 用于選擇圖片的 DOM 節(jié)點(diǎn)(Web)或者 File 對(duì)象(Web)或者微信小程序 wx.chooseImage 接口的 success 回調(diào)參數(shù)。SDK 會(huì)讀取其中的數(shù)據(jù)并上傳圖片 |

示例

// Web 端發(fā)送圖片消息示例1 - 傳入 DOM 節(jié)點(diǎn)
// 1. 創(chuàng)建消息實(shí)例,接口返回的實(shí)例可以上屏
let message = tim.createImageMessage({
  to: 'user1',
  conversationType: TIM.TYPES.CONV_C2C,
  // 消息優(yōu)先級(jí),用于群聊(v2.4.2起支持)。如果某個(gè)群的消息超過(guò)了頻率限制,后臺(tái)會(huì)優(yōu)先下發(fā)高優(yōu)先級(jí)的消息,詳細(xì)請(qǐng)參考 消息優(yōu)先級(jí)與頻率控制
  // 支持的枚舉值:TIM.TYPES.MSG_PRIORITY_HIGH, TIM.TYPES.MSG_PRIORITY_NORMAL(默認(rèn)), TIM.TYPES.MSG_PRIORITY_LOW, TIM.TYPES.MSG_PRIORITY_LOWEST
  // priority: TIM.TYPES.MSG_PRIORITY_NORMAL,
  payload: {
    file: document.getElementById('imagePicker'),
  },
  onProgress: function(event) { console.log('file uploading:', event) }
});
// 2. 發(fā)送消息
let promise = tim.sendMessage(message);
promise.then(function(imResponse) {
  // 發(fā)送成功
  console.log(imResponse);
}).catch(function(imError) {
  // 發(fā)送失敗
  console.warn('sendMessage error:', imError);
});
// Web 端發(fā)送圖片消息示例2- 傳入 File 對(duì)象
// 先在頁(yè)面上添加一個(gè) ID 為 "testPasteInput" 的消息輸入框,例如 <input type="text" id="testPasteInput" placeholder="截圖后粘貼到輸入框中" size="30" />
document.getElementById('testPasteInput').addEventListener('paste', function(e) {
  let clipboardData = e.clipboardData;
  let file;
  let fileCopy;
  if (clipboardData && clipboardData.files && clipboardData.files.length > 0) {
    file = clipboardData.files[0];
    // 圖片消息發(fā)送成功后,file 指向的內(nèi)容可能被瀏覽器清空,如果接入側(cè)有額外的渲染需求,可以提前復(fù)制一份數(shù)據(jù)
    fileCopy = file.slice();
  }
  if (typeof file === 'undefined') {
    console.warn('file 是 undefined,請(qǐng)檢查代碼或?yàn)g覽器兼容性!');
    return;
  }
   // 1. 創(chuàng)建消息實(shí)例,接口返回的實(shí)例可以上屏
  let message = tim.createImageMessage({
    to: 'user1',
    conversationType: TIM.TYPES.CONV_C2C,
    payload: {
      file: file
    },
    onProgress: function(event) { console.log('file uploading:', event) }
  });  
  // 2. 發(fā)送消息
  let promise = tim.sendMessage(message);
  promise.then(function(imResponse) {
    // 發(fā)送成功
    console.log(imResponse);
  }).catch(function(imError) {
    // 發(fā)送失敗
    console.warn('sendMessage error:', imError);
  });
});

二. 撤回消息

撤回單聊消息或者群聊消息。撤回成功后,消息對(duì)象的 isRevoked 屬性值為 true。

示例

// 主動(dòng)撤回消息
let promise = tim.revokeMessage(message);
promise.then(function(imResponse) {
// 消息撤回成功
}).catch(function(imError) {
// 消息撤回失敗
console.warn('revokeMessage error:', imError);
});
tim.on(TIM.EVENT.MESSAGE_REVOKED, function(event) {
// 收到消息被撤回的通知。使用前需要將 SDK 版本升級(jí)至v2.4.0或以上。
// event.name - TIM.EVENT.MESSAGE_REVOKED
// event.data - 存儲(chǔ) Message 對(duì)象的數(shù)組 - [Message] - 每個(gè) Message 對(duì)象的 isRevoked 屬性值為 true
});
// 獲取會(huì)話的消息列表時(shí)遇到被撤回的消息
let promise = tim.getMessageList({conversationID: 'C2Ctest', count: 15});
promise.then(function(imResponse) {
const messageList = imResponse.data.messageList; // 消息列表
messageList.forEach(function(message) {
  if (message.isRevoked) {
    // 處理被撤回的消息
  } else {
    // 處理普通消息
  }
});
});

三. 接收消息

接收消息需要通過(guò)事件監(jiān)聽(tīng)實(shí)現(xiàn)

let onMessageReceived = function(event) {
// event.data - 存儲(chǔ) Message 對(duì)象的數(shù)組 - [Message]
};
tim.on(TIM.EVENT.MESSAGE_RECEIVED, onMessageReceived);

1. 解析文本消息
如果您的文本消息只含有文字,則可以直接在 UI 上渲染出'xxxxxxx'文字。
含有 [呲牙] 內(nèi)容需要解析為的文本參考下方

const emojiMap = {         // 根據(jù)[呲牙]可匹配的路徑地址
'[微笑]': 'emoji_0.png',
'[呲牙]': 'emoji_1.png',
'[下雨]': 'emoji_2.png'
}
const emojiUrl = 'http://xxxxxxxx/emoji/'   // 為<img src="https://main.qcloudimg.com/raw/6be88c30a4552b5eb93d8eec243b6593.png"  style="margin:0;">圖片的地址
function parseText (payload) {
let renderDom = []
// 文本消息
 let temp = payload.text
 let left = -1
 let right = -1
 while (temp !== '') {
   left = temp.indexOf('[')
   right = temp.indexOf(']')
   switch (left) {
     case 0:
       if (right === -1) {
         renderDom.push({
           name: 'text',
           text: temp
         })
         temp = ''
       } else {
         let _emoji = temp.slice(0, right + 1)
         if (emojiMap[_emoji]) {    // 如果您需要渲染表情包,需要進(jìn)行匹配您對(duì)應(yīng)[呲牙]的表情包地址
           renderDom.push({
             name: 'img',
             src: emojiUrl + emojiMap[_emoji]
           })
           temp = temp.substring(right + 1)
         } else {
           renderDom.push({
             name: 'text',
             text: '['
           })
           temp = temp.slice(1)
         }
       }
       break
     case -1:
       renderDom.push({
         name: 'text',
         text: temp
       })
       temp = ''
       break
     default:
       renderDom.push({
         name: 'text',
         text: temp.slice(0, left)
       })
       temp = temp.substring(left)
       break
   }
 }
return renderDom
}
// 最后的 renderDom 結(jié)構(gòu)為[{name: 'text', text: 'XXX'}, {name: 'img', src: 'http://xxx'}......]
// 渲染當(dāng)前數(shù)組即可得到想要的 UI 結(jié)果,如:XXX<img src="https://main.qcloudimg.com/raw/6be88c30a4552b5eb93d8eec243b6593.png"  style="margin:0;">XXX<img src="https://main.qcloudimg.com/raw/6be88c30a4552b5eb93d8eec243b6593.png"  style="margin:0;">XXX[呲牙XXX]

2. 解析系統(tǒng)消息

function parseGroupSystemNotice (payload) {
const groupName =
    payload.groupProfile.groupName || payload.groupProfile.groupID
switch (payload.operationType) {
  case 1:
    return `${payload.operatorID} 申請(qǐng)加入群組:${groupName}`
  case 2:
    return `成功加入群組:${groupName}`
  case 3:
    return `申請(qǐng)加入群組:${groupName}被拒絕`
  case 4:
    return `被管理員${payload.operatorID}踢出群組:${groupName}`
  case 5:
    return `群:${groupName} 已被${payload.operatorID}解散`
  case 6:
    return `${payload.operatorID}創(chuàng)建群:${groupName}`
  case 7:
    return `${payload.operatorID}邀請(qǐng)你加群:${groupName}`
  case 8:
    return `你退出群組:${groupName}`
  case 9:
    return `你被${payload.operatorID}設(shè)置為群:${groupName}的管理員`
  case 10:
    return `你被${payload.operatorID}撤銷(xiāo)群:${groupName}的管理員身份`
  case 255:
    return '自定義群系統(tǒng)通知'
}
}

3. 解析群提示消息

function parseGroupTipContent (payload) {
switch (payload.operationType) {
  case this.TIM.TYPES.GRP_TIP_MBR_JOIN:
    return `群成員:${payload.userIDList.join(',')},加入群組`
  case this.TIM.TYPES.GRP_TIP_MBR_QUIT:
    return `群成員:${payload.userIDList.join(',')},退出群組`
  case this.TIM.TYPES.GRP_TIP_MBR_KICKED_OUT:
    return `群成員:${payload.userIDList.join(',')},被${payload.operatorID}踢出群組`
  case this.TIM.TYPES.GRP_TIP_MBR_SET_ADMIN:
    return `群成員:${payload.userIDList.join(',')},成為管理員`
  case this.TIM.TYPES.GRP_TIP_MBR_CANCELED_ADMIN:
    return `群成員:${payload.userIDList.join(',')},被撤銷(xiāo)管理員`
  default:
    return '[群提示消息]'
}
}

會(huì)話相關(guān)

1. 獲取某會(huì)話的消息列表

// 打開(kāi)某個(gè)會(huì)話時(shí),第一次拉取消息列表
let promise = tim.getMessageList({conversationID: 'C2Ctest', count: 15});
promise.then(function(imResponse) {
const messageList = imResponse.data.messageList; // 消息列表。
const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于續(xù)拉,分頁(yè)續(xù)拉時(shí)需傳入該字段。
const isCompleted = imResponse.data.isCompleted; // 表示是否已經(jīng)拉完所有消息。
});
// 打開(kāi)某個(gè)會(huì)話時(shí),第一次拉取消息列表
// 下拉查看更多消息
let promise = tim.getMessageList({conversationID: 'C2Ctest', nextReqMessageID, count: 15});
promise.then(function(imResponse) {
const messageList = imResponse.data.messageList; // 消息列表。
const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于續(xù)拉,分頁(yè)續(xù)拉時(shí)需傳入該字段。
const isCompleted = imResponse.data.isCompleted; // 表示是否已經(jīng)拉完所有消息。
});

2. 將會(huì)話設(shè)置為已讀

// 將某會(huì)話下所有未讀消息已讀上報(bào)
tim.setMessageRead({conversationID: 'C2Cexample'});

3. 獲取會(huì)話列表

// 拉取會(huì)話列表
let promise = tim.getConversationList();
promise.then(function(imResponse) {
const conversationList = imResponse.data.conversationList; // 會(huì)話列表,用該列表覆蓋原有的會(huì)話列表
}).catch(function(imError) {
console.warn('getConversationList error:', imError); // 獲取會(huì)話列表失敗的相關(guān)信息
});

4. 刪除會(huì)話

let promise = tim.deleteConversation('C2CExample');
promise.then(function(imResponse) {
//刪除成功。
const { conversationID } = imResponse.data;// 被刪除的會(huì)話 ID。
}).catch(function(imError) {
console.warn('deleteConversation error:', imError); // 刪除會(huì)話失敗的相關(guān)信息
});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容