经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » 微信小程序 » 查看文章
微信小程序websocket实现即时聊天功能
来源:jb51  时间:2019/5/22 8:31:13  对本文有异议

今天给大家分享一下本人做小程序使用websocket的一点小经验,希望对大家有所帮助。

使用之前肯定首先要了解一下websocket是什么,简单来讲websocket就是客户端与服务器之间专门建立的一条特殊通道,请求只需要请求一次,而且还可以从通道实时获取服务器数据,非常适合应用到实时应用上。

因为这里本人是分享小程序,所以就不去深究websocket的底层和协议了,感兴趣的朋友可以去看下websocket协议

建议大家在做之前先看看微信小程序官方提供的api关于websocket的文档,因为微信的websocket接口虽然和HTML5的websocket基本一样但是语法上还是有少许偏差,了解一下还是很有必要的。

话不多说上代码(css代码就不贴了,就是一些简单的聊天样式排版)

wxml

  1. <view>
  2. <scroll-view scroll-y="true" scroll-with-animation="true" scroll-x="false" scroll-into-view="list-{{idx}}" class="twnav">
  3. <view class='twChild'>
  4. <!-- <text>视频聊天室</text> -->
  5. <view class='tellRoom' wx:for="{{tellData}}" wx:for-index="idx" wx:for-item="li" wx:key="li" id='list-{{li.id}}'>
  6. <view class='myHead'>
  7. <image class='sayHead' wx-if='{{li.type=="question"||li.type=="message"}}' src='{{li.avatarurl}}'></image>
  8. <image class='sayHead' wx-if='{{li.type=="answer"}}' src='{{li.content.orgLogo}}'></image>
  9. </view>
  10. <view class='tellDetail'>
  11. <text class='name' wx-if='{{li.type=="question"||li.type=="message"}}'>{{li.displayName}}:</text>
  12. <text class='name' wx-if='{{li.type=="answer"}}'>{{li.content.orgName}}回复{{li.displayName}}:</text>
  13. <view wx-if='{{li.type=="answer"}}' class='answer'>
  14. <view class='anQue'>{{li.content.question}}</view>
  15. <view class='anAn'>{{li.content.answer}}</view>
  16. </view>
  17. <image wx-if='{{li.type=="question"}}' class='question' src='../../image/icon_quiz@2x.png' mode='widthFix'></image>
  18. <text class='sayDetail' wx-if='{{li.type=="question"}}'>{{li.content.content}}</text>
  19. <text class='sayDetail' wx-if='{{li.type=="message"}}'>{{li.content}}</text>
  20. </view>
  21. </view>
  22. <view class='ccds'></view>
  23. </view>
  24. </scroll-view>
  25. <view class='btn' wx-if='{{tell==true&&promodal==false}}'>
  26. <form bindreset="foo">
  27. <input class="myinput" placeholder="说点什么吧" bindinput="sayValue" focus='{{myinputing}}'/>
  28. <button form-type="reset" class='sub' wx-if='{{isSend=="send"||isSend=="sureAsk"}}' bindtap='sendMes'>发送</button>
  29. <button form-type="reset" class='sub' wx-if='{{isSend=="ask"}}' bindtap='ask'></button>
  30. </form>
  31. </view>
  32. </view>

js

  1. const app = getApp()
  2. var server = app.globalData.myUrl//这是自己的服务端接口地址设置于app.js
  3. var WxParse = require('../../wxParse/wxParse.js');
  4. var tellPage = 1
  5. var myurl='ws://+"你自己的链接地址"'
  6. var ws // socket发送的消息队列
  7. var socketMsgQueue = []
  8. var socketOpen = true // 判断心跳变量
  9. var heart = '' // 心跳失败次数
  10. var heartBeatFailCount = 0 // 终止心跳
  11. var heartBeatTimeOut = null; // 终止重新连接
  12. var connectSocketTimeOut = null;
  13. Page({
  14. /**
  15. * 页面的初始数据
  16. */
  17. data: {
  18. sayValue:'',
  19. tellData:[],//聊天消息
  20. idx:'',
  21. id:'',
  22. fjh:'',//房间号
  23. myinputing:'',
  24. isSend: 'ask',
  25. },
  26. /**
  27. * 生命周期函数--监听页面加载
  28. */
  29. onLoad: function (options) {
  30. this.setData({
  31. id: options.id,
  32. fjh:options.roomNum,
  33. })
  34. this.history(1)
  35. this.connectStart()
  36. },
  37. /**
  38. * 生命周期函数--监听页面初次渲染完成
  39. */
  40. onReady: function () {
  41. //监听websocket连接状态
  42. this.deal()
  43. },
  44. /**
  45. * 生命周期函数--监听页面显示
  46. */
  47. onShow: function () {
  48. console.log()
  49. },
  50. /**
  51. * 生命周期函数--监听页面隐藏
  52. */
  53. onHide: function () {
  54. },
  55. /**
  56. * 生命周期函数--监听页面卸载
  57. */
  58. onUnload: function () {
  59. var that = this
  60. //离开页面销毁websocket并恢复初始数据
  61. wx.closeSocket()
  62. twice = 0
  63. socketOpen = true
  64. heart = '' // 心跳失败次数
  65. heartBeatFailCount = 0 // 终止心跳
  66. heartBeatTimeOut = null; // 终止重新连接
  67. connectSocketTimeOut = null;
  68. },
  69. /**
  70. * 页面相关事件处理函数--监听用户下拉动作
  71. */
  72. onPullDownRefresh: function () {
  73. },
  74. /**
  75. * 页面上拉触底事件的处理函数
  76. */
  77. onReachBottom: function () {
  78. },
  79. /**
  80. * 用户点击右上角分享
  81. */
  82. onShareAppMessage: function () {
  83. console.log('点击分享')
  84. },
  85. //获取聊天室历史记录
  86. history: function (a) {
  87. var that = this
  88. wx.request({
  89. url: server + 'api/message/chatmsg',
  90. header: {
  91. "Authorization": app.globalData.token,
  92. },
  93. data: {
  94. page: a,
  95. type: '',
  96. resultsPerPage: 1000,
  97. stream: that.data.id
  98. },
  99. success: (res) => {
  100. var h = res.data.data.items
  101. if (h.length > 0) {
  102. var myArr = []
  103. var c = 0
  104. h.forEach(i => {
  105. c++
  106. i.id = c
  107. if (i.type == 'question' || i.type == 'answer') {
  108. i.content = JSON.parse(i.content)
  109. }
  110. myArr.push(i)
  111. })
  112. var j = h.length - 1
  113. var idx = h[j].id
  114. // console.log(h, idx)
  115. that.setData({
  116. tellData: h,
  117. idx: idx,
  118. })
  119. }
  120. }
  121. })
  122. },
  123. //与socket建立连接
  124. connectStart: function () {
  125. var that = this
  126. ws = wx.connectSocket({
  127. url: myurl,
  128. header: {
  129. "Authorization": app.globalData.token,
  130. 'content-type': 'application/json'
  131. },
  132. data: JSON.stringify({
  133. token: app.globalData.token,
  134. type: 3,
  135. payLoad: {
  136. topic: that.data.fjh
  137. }
  138. }),
  139. success: (res) => {
  140. // console.log("进入聊天", res)
  141. },
  142. fail: (err) => {
  143. wx.showToast({
  144. title: '网络异常!',
  145. })
  146. console.log(err)
  147. },
  148. })
  149. // 连接成功
  150. wx.onSocketOpen((res) => {
  151. console.log('WebSocket 成功连接', res)
  152. that.resMes()
  153. // 开始心跳
  154. that.startHeartBeat()
  155. })
  156. //连接失败
  157. wx.onSocketError((err) => {
  158. console.log('websocket连接失败', err);
  159. twice=0
  160. that.connectStart()
  161. })
  162. },
  163. // 开始心跳
  164. startHeartBeat: function () {
  165. // console.log('socket开始心跳')
  166. var that = this;
  167. heart = 'heart';
  168. that.heartBeat();
  169. },
  170. // 心跳检测
  171. heartBeat: function () {
  172. var that = this;
  173. if (!heart) {
  174. return;
  175. }
  176. var xtData = {
  177. token: app.globalData.token,
  178. type: 1,
  179. payLoad: ""
  180. }
  181. // console.log(JSON.stringify({ xtData }))
  182. that.sendSocketMessage({
  183. msg: JSON.stringify(xtData),
  184. data: JSON.stringify(xtData),
  185. success: function (res) {
  186. // console.log('socket心跳成功',res);
  187. if (heart) {
  188. heartBeatTimeOut = setTimeout(() => {
  189. that.heartBeat();
  190. }, 5000);
  191. }
  192. },
  193. fail: function (res) {
  194. console.log('socket心跳失败');
  195. if (heartBeatFailCount > 2) {
  196. // 重连
  197. console.log('socket心跳失败')
  198. that.connectStart();
  199. }
  200. if (heart) {
  201. heartBeatTimeOut = setTimeout(() => {
  202. that.heartBeat();
  203. }, 5000);
  204. }
  205. heartBeatFailCount++;
  206. },
  207. });
  208. },
  209. // 进入聊天
  210. resMes: function () {
  211. var that = this
  212. var joinData = {
  213. token: app.globalData.token,
  214. type: 3,
  215. payLoad: JSON.stringify({
  216. topic: that.data.fjh
  217. }),
  218. }
  219. // console.log(joinData)
  220. that.sendSocketMessage({
  221. msg: JSON.stringify(joinData),
  222. data: JSON.stringify(joinData),
  223. success: function (res) {
  224. // console.log('进入房间成功', res);
  225. that.deal()
  226. },
  227. fail: function (err) {
  228. console.log('进入房间失败');
  229. },
  230. })
  231. },
  232. // 结束心跳
  233. stopHeartBeat: function () {
  234. // console.log('socket结束心跳')
  235. var that = this;
  236. heart = '';
  237. if (heartBeatTimeOut) {
  238. clearTimeout(heartBeatTimeOut);
  239. heartBeatTimeOut = null;
  240. }
  241. if (connectSocketTimeOut) {
  242. clearTimeout(connectSocketTimeOut);
  243. connectSocketTimeOut = null;
  244. }
  245. },
  246. // 消息发送
  247. foo: function () {
  248. if (this.data.inputValue) {
  249. //Do Something
  250. } else {
  251. //Catch Error
  252. }
  253. this.setData({
  254. inputValue: ''//将data的inputValue清空
  255. });
  256. return;
  257. },
  258. sayValue: function (e) {
  259. var that = this
  260. // console.log(this.data.isSend)
  261. if (that.data.isSend == 'ask') {
  262. that.setData({
  263. isSend: 'send'
  264. })
  265. }
  266. that.setData({
  267. sayValue: e.detail.value
  268. })
  269. },
  270. sendMes: function (e) {
  271. var that = this
  272. // console.log(this.data.sayValue, 111)
  273. var myInput = this.data.sayValue
  274. var token = app.globalData.token
  275. if (that.data.isSend == 'sureAsk') {
  276. wx.request({
  277. url: server + 'api/question/add',
  278. method: 'POST',
  279. header: {
  280. "Authorization": app.globalData.token,
  281. 'content-type': 'application/json'
  282. },
  283. data: {
  284. content: myInput,
  285. streamId: that.data.id
  286. },
  287. success: (res) => {
  288. console.log(res, '我的提问')
  289. }
  290. })
  291. } else {
  292. // console.log(app.globalData.userInfo)
  293. var chatInfo = {
  294. user: app.globalData.userInfo.id,
  295. displayName: app.globalData.userInfo.displayName,
  296. avatarurl: app.globalData.userInfo.avatarUrl,
  297. stream: that.data.id,
  298. content: myInput,
  299. type: "message",
  300. createdat: "2018-10-8 14:30"
  301. }
  302. var sendData = {
  303. token: token,
  304. type: 2,
  305. payLoad: JSON.stringify({
  306. topic: that.data.fjh,
  307. chatInfo: JSON.stringify(chatInfo)
  308. })
  309. }
  310. // console.log(JSON.stringify(sendData))
  311. that.sendSocketMessage({
  312. msg: JSON.stringify(sendData)
  313. })
  314. }
  315. that.setData({
  316. sayValue: '',
  317. isSend: 'ask'
  318. })
  319. },
  320. // 通过 WebSocket 连接发送数据
  321. sendSocketMessage: function (options) {
  322. var that = this
  323. if (socketOpen) {
  324. wx.sendSocketMessage({
  325. data: options.msg,
  326. success: function (res) {
  327. if (options) {
  328. options.success && options.success(res);
  329. }
  330. },
  331. fail: function (res) {
  332. if (options) {
  333. options.fail && options.fail(res);
  334. }
  335. }
  336. })
  337. } else {
  338. socketMsgQueue.push(options.msg)
  339. }
  340. // ws.closeSocket();
  341. // that.deal()
  342. },
  343. // 监听socket
  344. deal: function () {
  345. var that = this
  346. ws.onOpen(res => {
  347. socketOpen = true;
  348. console.log('监听 WebSocket 连接打开事件。', res)
  349. })
  350. ws.onClose(onClose => {
  351. console.log('监听 WebSocket 连接关闭事件。', onClose)
  352. // socketOpen = false;
  353. // that.connectStart()
  354. })
  355. ws.onError(onError => {
  356. console.log('监听 WebSocket 错误。错误信息', onError)
  357. socketOpen = false
  358. })
  359. ws.onMessage(onMessage => {
  360. var res = JSON.parse(onMessage.data)
  361. // console.log(res,"接收到了消息")
  362. if (res.code == 200) {
  363. // console.log('服务器返回的消息', res.data)
  364. var resData = JSON.parse(res.data)
  365. var arr = that.data.tellData
  366. resData.id = arr.length + 1
  367. if (resData.type == 'question' || resData.type == 'answer') {
  368. resData.content = JSON.parse(resData.content)
  369. console.log('这是提问', resData.type, resData.content.content)
  370. }
  371. arr.push(resData)
  372. console.log(resData, arr.length)
  373. that.setData({
  374. tellData: arr,
  375. idx: resData.id
  376. })
  377. } else {
  378. }
  379. })
  380. },
  381. time: function (a) {
  382. var data = new Date(a)
  383. var year = data.getFullYear();
  384. var month = data.getMonth() + 1;
  385. var day1 = data.getDate();
  386. var hh = data.getHours(); //截取小时
  387. var mm = data.getMinutes(); //截取分钟
  388. if (month < 10) {
  389. month = '0' + month
  390. }
  391. if (day1 < 10) {
  392. day1 = '0' + day1
  393. }
  394. if (hh < 10) {
  395. hh = '0' + hh
  396. }
  397. if (mm < 10) {
  398. mm = '0' + mm
  399. }
  400. var newday = month + "月" + day1 + ' ' + hh + ':' + mm
  401. return newday
  402. },
  403. inputing: function () {
  404. console.log('获取焦点')
  405. this.setData({
  406. isSend: 'send'
  407. })
  408. },
  409. inputed: function () {
  410. // console.log('失去焦点')
  411. this.setData({
  412. isSend: 'ask',
  413. })
  414. },
  415. ask: function () {
  416. // console.log('提问')
  417. this.setData({
  418. myinputing: true,
  419. isSend: 'sureAsk'
  420. })
  421. },
  422. })

以上仅是前端部分本人小程序websocket的使用实例,具体的情况需要配合自己的服务端。希望对大家有所帮助,也欢迎大家互相讨论。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号