1. 前言
随着移动应用的快速发展,小程序成为越来越多企业选择的一个移动端应用开发方式。在小程序中,实现聊天功能是一个比较常见的需求。不过,聊天功能的实现并不容易,需要处理的问题比较多,比如即时通讯、聊天记录存储、图片、语音等资源的处理等等。为了方便开发者实现聊天功能,很多第三方平台提供了聊天sdk。本文将介绍如何在小程序中导入sdk实现聊天功能。
2. 导入聊天sdk
要在小程序中实现聊天功能,我们需要使用第三方平台提供的聊天sdk。这里以融云为例,介绍如何导入聊天sdk。
2.1 注册融云账号
首先,我们需要在融云官网上注册一个账号。地址为:https://www.rongcloud.cn/ 。注册账号之后,登录融云控制台,创建应用,获取App Key和App Secret。
2.2 下载sdk
在控制台首页,点击左侧的“聊天服务”,然后点击“SDK下载”,下载适用于小程序的sdk。将sdk解压缩,包含以下文件:
rcloud.js是融云小程序sdk的主要代码文件
md5.js用于生成加密签名字符串的js文件
2.3 引入sdk文件
将rcloud.js和md5.js文件放到小程序的根目录下,然后在app.js中引入rcloud.js文件。
// app.js中引入rcloud.js文件
const rcloud = require('./rcloud.js')
// 初始化rongcloud sdk
const rong = rcloud.init({
appkey: 'yourAppKey',
secret: 'yourAppSecret'
})
在代码中需要替换掉yourAppKey和yourAppSecret为申请融云账号时的App Key和App Secret。现在聊天sdk已经可以使用了。
3. 实现聊天功能
以上我们已经成功导入了聊天sdk,接下来我们需要在小程序中实现聊天功能。本文将用微信小程序为例,介绍如何实现聊天功能。
3.1 登录融云
在实现聊天功能之前,我们需要登录融云服务器。
在app.js中,添加login方法:
// app.js中添加login方法
login() {
const that = this
wx.login({
success: res => {
that.globalData.code = res.code
// 将code发送到后台换取sessionId等信息
// 发起ajax请求,POST params: {code: res.code}, url: /api/login,请求成功后向消息中心订阅消息
wx.request({
url: 'https://yourdomain.com/api/login',
data: { code: that.globalData.code },
method: 'POST',
success: res => {
that.globalData.sessionId = res.data.sessionId
// 登录融云服务器
rong.rcloudlib.RongIMSDK.connect(that.globalData.sessionId, {
onSuccess: function(userId) {
console.log("Connect successfully!" + userId)
},
onTokenIncorrect: function() {
console.log('token无效')
},
onError: function(errorCode) {
console.log(errorCode)
}
})
},
fail: () => {
wx.showToast({
title: '加载失败',
icon: 'none'
})
}
})
}
})
}
在app.js的onLaunch方法中调用login方法:
// app.js中onLaunch方法中调用login方法
onLaunch: function () {
this.login()
}
3.2 加载会话列表
在聊天室中,我们需要通过会话列表展示用户的会话记录。下面,我们来实现加载会话列表的功能。
在pages/index文件夹下面,创建一个文件session.js,并编写会话列表相关的代码。
const app = getApp()
/**
* 获取会话列表
*/
function getConversationList() {
return new Promise((resolve, reject) => {
app.data.conversationList = []
// 获取会话列表
rong.rcloudlib.RongIMClient.getInstance().getConversationList({
onSuccess: function(list) {
list.sort((a, b) => {
return b.sentTime - a.sentTime
})
for (let i = 0; i < list.length; i++) {
let conversation = {}
conversation.id = list[i].targetId
conversation.unreadCount = list[i].unreadMessageCount
conversation.sentTime = list[i].sentTime
conversation.objName = list[i].latestMessage ? list[i].latestMessage.objectName : ''
conversation.latestMsg = list[i].latestMessage
app.data.conversationList.push(conversation)
}
resolve(app.data.conversationList)
},
onError: function(error) {
reject(error)
}
}, { // 获取的会话类型的数组,
conversationTypes: [rong.rcloudlib.ConversationType.PRIVATE],
// 获取会话中的最新消息内容,此处为文本消息内容。
latestMessageTypes: [rong.rcloudlib.MessageType.Text],
count: 20 // 获取会话列表最多数量,默认值为 100,最大值为 1000。
})
})
}
module.exports = {
getConversationList: getConversationList
}
在index.js中调用getConversationList方法,获取会话列表并在页面上展示:
const session = require('../../session.js')
Page({
data: {
conversationList: []
},
onLoad: function() {
// 获取会话列表
session.getConversationList().then(data => {
this.setData({
conversationList: data
})
})
}
})
3.3 展示聊天内容
在会话列表中,我们需要展示聊天内容。下面,我们通过页面跳转,展示聊天记录。
在pages/chat文件夹下面,创建页面chat。chat页面将用于展示聊天记录。
const app = getApp()
Page({
data: {
messageList: []
},
onLoad: function(options) {
// 获取会话历史消息
app.data.messageList = []
rong.rcloudlib.RongIMClient.getInstance().getHistoryMessages(
rong.rcloudlib.ConversationType.PRIVATE, // 确定会话类型
options.targetId, // 目标 Id,根据不同的会话类型可能是用户 Id、群组 Id。
'', // 消息时间戳,获取该时间戳之前的所有消息。
20, //获取的消息数,最大值为 20。
{
onSuccess: function(list, has) {
console.log(list)
for (let i = 0; i < list.length; i++) {
var message = {}
message.content = list[i].content.content
app.data.messageList.push(message)
}
console.log(app.data.messageList)
that.setData({
messageList: app.data.messageList.reverse()
})
},
onError: function(error) {
console.log(error)
}
}
)
}
})
在会话列表中通过setData方法更新代码。
const session = require('../../session.js')
Page({
data: {
conversationList: []
},
onLoad: function() {
// 获取会话列表
session.getConversationList().then(data => {
this.setData({
conversationList: data
})
})
},
/**
* 跳转到聊天界面
*/
gotoChatPage(event) {
let id = event.currentTarget.dataset.id
console.log('临时会话id:' + id)
wx.navigateTo({
url: '/pages/chat/chat?targetId=' + id
})
}
})
3.4 发送消息
下面我们来实现发送消息的功能。
在chat.js中,添加sendMessage方法。
/**
* 发送消息
*/
function sendMessage(content, targetId) {
return new Promise((resolve, reject) => {
// 创建消息实例
let msg = new rong.rcloudlib.TextMessage({
content: content,
extra: "附加信息"
})
let conversationtype = rong.rcloudlib.ConversationType.PRIVATE // 单聊
// 发送消息
rong.rcloudlib.RongIMClient.getInstance().sendMessage(conversationtype, targetId, msg, {
onSuccess: function(message) {
console.log("Send successfully")
resolve(message)
},
onError: function(error) {
console.log("Send Error:" + error)
reject(error)
}
})
})
}
module.exports = {
sendMessage: sendMessage
}
在chat页面中,发送消息:
const app = getApp()
const chat = require('../../chat.js')
Page({
data: {
content: '',
targetId: ''
},
onLoad: function(options) {
this.setData({
targetId: options.targetId
})
},
/**
* 发送消息
*/
send(event) {
let that = this
if (that.data.content == '') {
wx.showToast({
title: '消息不能为空',
icon: 'none',
duration: 2000
})
return
}
chat.sendMessage(that.data.content, that.data.targetId).then(message => {
let obj = {}
obj.content = message.content.content
app.data.messageList.push(obj)
that.setData({
messageList: app.data.messageList,
content: ''
})
})
}
})
4. 问题解决
4.1 聊天室不是实时更新
对于大多数聊天室应用而言,最重要的特性是实时的数据更新。但是,在小程序中,网络通信的实时性是无法保证的。
实时更新的解决办法是,使用轮询机制来定时获取数据。具体做法是:使用setInterval函数每隔一段时间就发送一次ajax请求,获取最新的聊天记录。
下面是一个定时器方法,每5秒获取一次聊天记录:
/**
* 获取会话历史消息
* 时间戳:time:undefined
* count:limit
* 显示消息排序:false
* showCreateDate:false
*/
function polling(index) {
const that = this
setInterval(() => {
// 获取最新的聊天记录
rong.rcloudlib.RongIMClient.getInstance().getHistoryMessages(
rong.rcloudlib.ConversationType.PRIVATE, // 确定会话类型
this.data.targetId, // 目标 Id,根据不同的会话类型可能是用户 Id、群组 Id。
'', // 消息时间戳,获取该时间戳之前的所有消息。
20, // 获取的消息数,最大值为 20。
{
onSuccess: function(list, has) {
console.log(list)
for (let i = 0; i < list.length; i++) {
var message = {}
message.content = list[i].content.content
that.data.messageList.push(message)
}
console.log('messageList')
console.log(that.data.messageList)
that.setData({
messageList: that.data.messageList,
index: that.data.messageList.length - 1
})
},
onError: function(error) {
console.log(error)
}
}
)
}, 5000)
}
module.exports = {
polling: polling
}
4.2 页面渲染问题
当点击会话列表中的某一个会话,跳转到聊天页面时,消息并没有立即显示出来。这是由于聊天页面数据还未加载,应该监听小程序onReady事件,等页面数据加载完成之后,再执行polling方法并渲染页面。
const app = getApp()
const chat = require('../../chat.js')
const session = require('../../session.js')
Page({
data: {
content: '',
targetId: '',
messageList: []
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
this.setData({
targetId: options.targetId
})
},
onReady: function() {
// 获取会话历史消息
chat.getMessageHistory(this.data.targetId).then((data)=>{
this.setData({
messageList:data,
index: data.length - 1
})
}).then(() => {
// 轮询获取最新的聊天记录
chat.polling(this.data.index)
})
},
})
5. 总结
本文介绍了如何在小程序中导入sdk,使用融云sdk为例,实现了聊天功能。在小程序中实现聊天功能需要处理很多问题,如登录融云服务器、加载会话列表、展示聊天内容、发送消息等等。通过本文的介绍可以清楚地了解聊天室的开发过程,并且对于其他类型应用也有一定的参考意义。