作者:陈畏民

源起

今年寒假的前半段时间, 在家捣鼓了一个情侣类web应用, 基于aspnetcore和angular搭建的; 寒假中实现了'告白', '相册', '说说', '纪念日'这些功能, 然后前端界面上留一个功能的坑位: 聊天, 点击这个聊天按钮, 可以看到四个字, 那就是敬请期待; 部署上线后, 用户当然只有我和我的"好朋友"使用, "好朋友"先跨了我真棒, 然后问聊天功能马上可以用了吧? 我沉默了, 心想着这个功能后面用signalr试试看吧; 现在已经2020秋了, 聊天功能的界面上依旧是那四个字: 敬请期待

这个国庆, 我意识到不能再拖了, 自己埋的坑, 应该趁早把它填了, 否则"好朋友"会觉得你很菜, 一个"简单的"聊天功能都做不出来;

遇见声网(agora)

最开始想用signalr自己实现聊天功能的, 但是考虑到一方面, 自己的服务器资源有限(1核1G轻量应用服务器); 另一方面, 自身精力能力有限, 写出来也许不难, 但是要写好确是不简单的; 于是寻思着找找现成的东西用用吧, 机缘巧合, 我听说了声网(agora), 于是去他的官网看了一番, 看到有详细的文档, 足量的免费额度...于是决定先白嫖试用一下

关于agora

特地找了一下agora的相关资料, 看起来是挺靠谱的, 在全球都有数据中心和服务器; 小米、陌陌、新东方等知名企业都用过他们的云服务;

基于agora的rtm sdk给我的应用加上聊天功能

参考官网的文档

我的环境

  • win10系统
  • npm包管理
  • angular8.x
  • vscode

步骤

安装依赖

npm i agora-rtm-sdk
安装完后需要修改下agora-rtm-sdk/index.d.ts的文件的2258
原来的内容为:

export type { RtmChannel, RtmClient, RtmEvents, RtmMessage, RtmStatusCode };

修改为:

export { RtmChannel, RtmClient, RtmEvents, RtmMessage, RtmStatusCode };

不修改的话, 编译会报错

引入依赖

因为是在在angular组件ChatComponent中实现聊天相关的功能, 所以在其中引入rtm sdk的依赖 import AgoraRTM from 'agora-rtm-sdk';

创建rtm客户端并登陆到agora的rtm服务器

一行代码创建rtm客户端:

const rtmClient = AgoraRTM.createInstance('<your app id>');

<details>
<summary>登陆到rtm服务器</summary>

const rtmClient = AgoraRTM.createInstance('fd033b52ca5d40599efc96f6e2131639');async function rtmClientLogin(user: User) {try {await rtmClient.login({ token: null, uid: user.id });} catch(err) {console.log('AgoraRTM client login failure', err);}
}// 在组件的 ngOnInit 方法中调用 rtmClientLogin
async ngOnInit() {try {let user = await this.userServ.getUser().toPromise();if (user instanceof User) {this.user = user;rtmClientLogin(this.user);} else {throw new Error('无法获取用户数据');}} catch(err) {this.notifyServ.error('初始化聊天组件失败', null);console.error('初始化聊天组件失败', err);}}

ps: 测试阶段, 所以使用的rtm的授权方式是AppID, 如果要使用这种授权方式, 在rtm控制台创建项目的时候要注意一下, 身份认证模式勾选 App ID, 否则在登陆到rtm服务器的时候, 会报红

发送/接收消息

消息发送失败需要通知用户, 错误通知直接使用了antdesign的NzNotificationService, 在构造函数注入即可; 这个应用中, 互相发消息的双方是情侣, User表示当前用户, User.Spouse表示用户的伴侣; 消息发送成功需要清空发送消息文字框并将发送的消息加入消息数组中, 让angular更新视图

发送消息

async sendMessage() {if (!this.newMessage) {return;}const spouseId = this.user.spouse.id;try {const result = await rtmClient.sendMessageToPeer({text: this.newMessage}, spouseId);if (!result.hasPeerReceived) {throw new Error('对方未接受消息');} else {this.messages.push({text: this.newMessage,sender: this.user,receiver: this.user.spouse,dateSended: new Date()});this.newMessage = undefined;}} catch (err) {this.notifyServ.error('发送消息失败', null);console.log('发送消息失败', err);}
}

ngOnInit生命周期函数中监听收到新消息事件, 收到新消息后, 将新消息加入消息数组中, angular会通过数据绑定更新视图, 渲染ui

监听并处理收到新消息事件

async ngOnInit() {try {let user = await this.userServ.getUser().toPromise();if (user instanceof User) {this.user = user;rtmClientLogin(this.user);监听接收到消息事件rtmClient.on('MessageFromPeer', (rtmMessage, peerId) => {this.messages.push({text: rtmMessage.text,sender: this.user.spouse,receiver: this.user,dateSended: new Date()});});} else {throw new Error('无法获取用户数据');}} catch(err) {this.notifyServ.error('初始化聊天组件失败', null);console.error('初始化聊天组件失败', err);}
}

前端html代码

<div id="container"><div class="messages"><div class="message-item"*ngFor="let msg of messages"><div class="sendedMessage"*ngIf="msg.sender.id === user.id"><span class="message-text">{{msg.text}}</span><span><nz-avatar nzIcon="user"[nzSrc]="msg.receiver.profileImageUrl"></nz-avatar></span></div><div class="receviedMessage"*ngIf="msg.sender.id === user.spouse.id"><span><nz-avatar nzIcon="user"[nzSrc]="msg.sender.profileImageUrl"></nz-avatar></span><span class="message-text">{{msg.text}}</span></div></div></div><div class="new-message"><div nz-rownzJustify="end"><div nz-colnzSpan="18"><textarea nz-input[(ngModel)]="newMessage"[nzAutosize]="{ minRows: 1, maxRows: 6 }"></textarea></div><div nz-colnzSpan="6"><button nz-buttonnzType="primary"class="mx-auto"style="width: 100%;"(click)="sendMessage()">发送</button></div></div></div>
</div>

前端css

:host {height: 100%;display: block;position: relative;
}#container {height: 100%;display: flex;flex-direction: column;padding-top: 4px;
}.messages {flex-grow: 1;
}nz-alert {display: block;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 85%;text-align: center;
}.sendedMessage {display: flex;justify-content: flex-end;align-items: center;margin-bottom: 8px;
}.receviedMessage {margin-bottom: 8px;
}.message-text {background: #fff;padding: 8px 4px;
}.sendedMessage .message-text {margin-right: 4px;
}.receviedMessage .message-text {margin-left: 4px;
}

效果如何?

动图演示:

静图:

小结

上文基于agora的rtm sdk, 初步实现了简单的聊天功能; 体验下来感觉很方便, 不需要关注后端实现, 只需要处理前端逻辑即可轻松构建出实时聊天功能; 当然, 正式在生产环境使用, 还是需要后端配合生成一个身份认证令牌(token)来保证安全性的; 上文暂时只实现了文字的发送接收, 实际上rtm sdk还支持文件和图片的收发, 功能很强大, 有机会再继续探索。


本文是参与声网"内容共建计划"的开发者投稿作品

了解更多实时互动相关内容可点击进入声网RTC 开发者社区进行查看

使用声网的RTM SDK轻松给angular应用加上实时聊天功能相关推荐

  1. 声网Agora Native SDK 2.9.3 发布

    新年伊始,开工大吉! 声网 Agora Native SDK 2.9.3 现在已经正式发布,并已更新至官网开发者中心的「SDK和应用下载」页面.新版本面向Android.iOS.macOS.Windo ...

  2. 声网 agora php sdk,快速了解声网Agora SDK 3.0

    声网 Agora Native SDK 3.0 ,以及 Web SDK 3.0.2 ,已经正式发布上线一段时间了. 新版本 SDK 采用了全新的系统架构和下一代实时编码传输技术,同时还新增了许多新功能 ...

  3. 利用云信SDK实现前端实时聊天功能

    前言:由于项目中有聊天的功能,会根据不同的状态,来判断哪些角色的人可以参与聊天,或者结束聊天等等.由于历史原因,项目不能使用websocket  来实现实时通信,所以就使用了云信的SDK,来实现实时聊 ...

  4. 基于声网 Agora 信令 SDK 开发聊天室应用(一)

    文章作者:monkeyHi 本文是 声网 Agora 开发者的投稿.如有疑问,欢迎与作者交流. 社会高度发展的今天,大家都离不开社交和社交网络.近几年,直播行业的稳定高速发展,背后隐藏一个事实,大家需 ...

  5. 声网关闭(打开)摄像头,翻转摄像头,静音功能(vue)

    视频通话 - 文档中心 - 声网Agora 若想实现以下功能,请确保已经完成可加入房间,可正常通讯等流程! 创建本地端&&远程端代码: let rtc = {// For the lo ...

  6. 让游戏聊天消息、信令控制更实时、可靠,声网实时消息 RTM SDK Unity版上线

    我们在去年推出了Agora RTC SDK Unity 版,并上线 Unity Asset Store.随着 Unity 社区需求的不断增加,近期 Unity 版的声网Agora 实时消息 RTM S ...

  7. 一夜爆红的“隐形巨头”,声网Agora还能否发出新“声量”?

    今年年初,一款名为Clubhouse的即时音频社交产品在大洋彼岸飞速走红,而在超级网红马斯克的一个直播房间,更是将其推向了热议的顶点. 随着这款产品的爆火,在幕后为其提供足以容纳5000人实时语音交流 ...

  8. 保姆级教程!基于声网 Web SDK实现音视频通话及屏幕共享

    前言 大家好,我是 @小曾同学,小伙伴们也可以叫我小曾- 如果你想实现一对一音视频通话和屏幕共享功能,不妨来看看这篇文章,保姆级教程,不需要从零实现,直接集成声网 SDK 即可轻松上手. 本文也分享了 ...

  9. 基于声网 视频通话SDK 的opencv 人脸检测

    目前在用声网的 视频通话SDK 制作一款会议系统软件,将来可能要加入人脸的一些操作,因此就想到了opencv,并且声网SDK 也提供了原始的视频帧 回调函数,所以在此基础上集成opencv 是可以的. ...

最新文章

  1. 让迅雷的胃口变得更大!
  2. [资料分享]GIS+=地理信息+云计算+大数据+容器+物联网+...论文、会议、讲座资料分享...
  3. mongodb windwos 安装(转)
  4. sublime2使用和配置
  5. 信息学奥赛一本通(2047:【例5.16】过滤空格)
  6. oracle 2018 深圳大会,2018中国科幻大会深圳时间、地点、亮点
  7. InfoPath读取数据库
  8. 构建LVS+Keepalived高可用群集
  9. tomcat版本区别
  10. beini安装破*WIFI
  11. 蓝桥杯官网练习系统基础练习(十一)
  12. 基于FPGA的关于flash一些学习记录
  13. 录制线上课程,有哪些形式,到底使用什么软件好?
  14. mysql事务prepare_mysql之 事务prepare 与 commit 阶段分析
  15. 全国哀悼日,网站变黑白完美兼容IE,亲测有效
  16. 【Android -- 职业】职业规划
  17. [笔录]博客及源程序 出处
  18. PD虚拟机如何设置内存和CPU核心数
  19. poi-java导出word的表格中换行
  20. 如何笔记本盖上连接显示器不熄屏?

热门文章

  1. 分区表与普通表之间切换的报错
  2. 2017秋招第一面--阿里巴巴
  3. 转义字符的意义何在?
  4. 期货中的正向交易与反向交易
  5. 应聘中巧用积极的心理暗示
  6. Arduino驱动OLED显示屏
  7. 银行定期存三个月利息计算机公式,银行存款利息如何计算?如定期三个月,半年、一年、二年 爱问知识人...
  8. 完美世界刘航:异构计算要避免昙花一现
  9. 微信公众号开发---自定义菜单的创建及菜单事件响应(java)
  10. Keil自定义关键字、快捷键···