写在前面
在调用环信的消息回执时,是否有以下的烦恼
1、发送了消息已读回执,为什么消息列表页的未读数没有发生变化?
2、发送了消息已读回执,为什么消息漫游拉取不到已读状态?
如果你有这些烦恼,那就继续往下看
一些歧义
在这之前,我们需要先来统一确定两件事情
第一:消息列表页
第二:聊天页面
接下来以环信vue-demo为例,看一下这两者
如图所示,红色圈起来的部分为消息列表页也叫会话列表页面,可通过会话列表的api拉取。
绿色圈起来的部分为聊天页面,可通过消息漫游的api拉取
注:聊天页面的数据获取不是必须调用消息漫游api,也可以存在本地从本地进行获取,这个可根据自己项目的需求以及业务逻辑来做调整,本文以消息漫游中的数据为例
插播:会话是什么,当和一个用户或者在一个群中发消息后,就会自动把对方加到会话列表中,可以通过调用会话列表去查询。
需要注意
1、此api调用有延迟,建议只有初次登录时通过此api获取到初始会话列表的数据,后续都在本地进行维护。
2、登陆ID不要大小写混用的ID,拉取会话列表大小写ID混用会出现拉取会话列表为空
解决问题一:
在明确了会话列表页和聊天页面各代指的部分之后,我们先来解决第一个问题:
发送了消息已读回执,为什么会话列表的未读数没有变化
原因:对于环信来讲,消息是消息,会话是会话,这是两个概念,消息已读和会话已读并没有做联动,也就是消息已读只是对于这条消息而言并不会对会话列表的未读数产生影响,他们是两个独立的个体。会话列表的未读数是针对整个会话而言
那么如何清除会话列表的未读数呢?——需要发送会话已读回执也就是channel ack,这里还需要注意一点,sdk是只负责数据传输的,改变不了页面层的渲染逻辑。所以在发送完channel ack后页面上渲染的未读数不会无缘无故就清0了,是需要重新调用api渲染的!!!!!
channelAck() {
let option = {
chatType: "", // 会话类型,设置为单聊。
type: "channel", // 消息类型。固定参数固定值,不要动它
to: "", // 接收消息对象(用户 ID)。
};
let msg = WebIM.message.create(option);
WebIM.conn
.send(msg)
.then((res) => {
console.log("%c>>>>>>>>会话已读回执发送成功", "color:#6ad1c7", res);
})
.catch((e) => {
console.log("%c>>>>>>>>>会话已读回执发送失败", "color:#ef8784", e);
});
},
会话已读回执发送成功之后,接收方会收到onChannelMessage
回调监听
conn.addEventHandler("customEvent", {
onChannelMessage: (message) => {},
});
消息已读回执是需要发送readack,是针对于某一条消息而言。这里也需要注意一点,sdk是只负责数据传输的,改变不了页面层的渲染逻辑,所以已读未读在页面上的渲染也是需要自己处理一下
readAck() {
let option = {
type: "read", // 消息是否已读。固定参数固定值,不要动它
chatType: "singleChat", // 会话类型,这里为单聊。
to: "", // 消息接收方(用户 ID)。
id: "", // 需要发送已读回执的消息 ID。
};
let msg = WebIM.message.create(option);
WebIM.conn
.send(msg)
.then((res) => {
console.log("%c>>>>>>>>消息已读回执发送成功", "color:#6ad1c7", res);
})
.catch((e) => {
console.log("%c>>>>>>>>>消息已读回执发送失败", "color:#ef8784", e);
});
},
消息已读回执发送成功之后,接收方会收到onReadMessage
回调监听
conn.addEventHandler("customEvent", {
onReadMessage: (message) => {},
});
插播:会话列表未读数计算规则,简单理解,如果这个会话是单个用户在一直输出的话,这个未读数会一直累加,但是只要对方回了这条消息,那么未读数就会从这条消息之后开始再计算
解决问题二:
再来看一下第二个问题:为什么消息漫游中拉取不到消息的已读状态
原因:环信服务器是不记录消息状态的,也就是不会记录这条消息是否已读了,所以不会返回消息已读或者未读
那么如何来实现
1、自己本地进行记录消息状态
2、可以使用环信sdk提供的reaction功能来间接是实现已读未读
reaction实现已读未读简单示例
addReaction() {
WebIM.conn
.addReaction(
{
messageId: "",//消息ID
reaction: "read" //reaction
}
)
.then((res) => {
console.log("%c>>>>>>>>reaction添加成功", "color:#6ad1c7", res);
})
.catch((e) => {
console.log("%c>>>>>>>>>reaction添加失败", "color:#ef8784", e);
});
},
总结Q&A
Q:发送了消息已读回执,为什么消息列表页的未读数没有发生变化?
A:会话和消息是两个概念,会话已读是会话已读,消息已读是消息已读,消息已读无法改变会话列表的数据
Q:发送了消息已读回执,为什么消息漫游拉取不到已读状态?
A:环信的服务器不记录消息状态,需要自己本地存储或者使用reaction功能间接实现