IM即时聊天场景中,在发送多媒体消息(图片/音频/视频等)时,如果选中了多个多媒体文件一起发送,如何更快地将消息发送出去,且消息顺序和多媒体文件选择顺序保持一致?
简单的实现并不难,主要是如何尽可能地优化性能和用户体验。
分享一下个人的实现及后续优化的过程。
(以图片为例)
一、简单实现
实现逻辑:
- 1、拿到所有图片文件的file对象列表
fileList - 2、遍历
fileList,调用上传接口uploadFile,等待异步上传结果,依次串行上传。 - 3、每上传成功一张图片,就调用一次
sendMsg接口将该图片消息发送出去。
示例代码:
async handleFileList (fileList) {
for (let i = 0; i < fileList.length; i++) {
const res = await api.uploadFile(fileList[i].file)
api.sendMsg(res.url)
}
}
注意事项:
- 这里利用
for循环和async、await的特性,遍历fileList实现等待上次循环异步结束后再执行下次循环。(不能使用forEach遍历,因为forEach是通过回调函数执行逻辑,每次循环的回调都相互独立)。
思考:
- 虽然使用串行上传能保证消息发送的顺序一致,但细想一下,如果使用并行上传肯定能节省很多时间,只是不同大小的图片上传时间不一,如何处理消息发送的时机,使消息顺序保持一致?
其他方案:
Promise.all。Promise.all需等待所有接口成功后才能拿到结果,无法第一时间发送消息;且一个接口失败会中断所有异步接口。Promise.allSettled。Promise.allSettled需等待所有接口完成后才能拿到结果,无法第一时间发送消息。
以上也是我刚开始做这个需求时的实现历程,不管怎么说,先实现需求效果,完成上线,后面再考虑优化。
二、性能优化
主要优化点就是将上述的图片串行上传改为并行上传。
逻辑思路:
- 使用消息队列存储所有图片文件的上传状态和结果,每次上传完成后都检查队列,判断顺序和状态,符合条件的依次发送消息。
先上 消息队列类msgQueue.js 的完整代码:
class MsgQueue {
constructor () {
this.list = [] // 队列存储数组
this.isExecuting = false // 是否正在执行队列(防止异步时队列执行重复)
this.onCompleteAll = () => {
} // 消息队列全部完成后的回调
}
// 添加队列(length: 新添加的队列长度)
addList (length) {
const newList = new Array(length).fill().map(() => ({
status: 'pending', // pending:等待上传结果, success:上传成功, fail:上传失败, done:已发送消息
result: {
},
}))
const insertIndex = this.list.length
this.list = this

介绍了一种在即时通讯应用中优化批量图片发送的方法,通过并行上传和串行发送确保消息顺序一致,提升用户体验。
最低0.47元/天 解锁文章
1327

被折叠的 条评论
为什么被折叠?



