微信小程序websocket实现即时聊天功能
今天给大家分享一下本人做小程序使用websocket的一点小经验,希望对大家有所帮助。
使用之前肯定首先要了解一下websocket是什么,简单来讲websocket就是客户端与服务器之间专门建立的一条特殊通道,请求只需要请求一次,而且还可以从通道实时获取服务器数据,非常适合应用到实时应用上。
因为这里本人是分享小程序,所以就不去深究websocket的底层和协议了,感兴趣的朋友可以去看下websocket协议
建议大家在做之前先看看微信小程序官方提供的api关于websocket的文档,因为微信的websocket接口虽然和HTML5的websocket基本一样但是语法上还是有少许偏差,了解一下还是很有必要的。
话不多说上代码(css代码就不贴了,就是一些简单的聊天样式排版)
wxml
{{li.displayName}}: {{li.content.orgName}}回复{{li.displayName}}: {{li.content.question}} {{li.content.answer}} {{li.content.content}} {{li.content}} 发送 问
js
constapp=getApp() varserver=app.globalData.myUrl//这是自己的服务端接口地址设置于app.js varWxParse=require('../../wxParse/wxParse.js'); vartellPage=1 varmyurl='ws://+"你自己的链接地址"' varws//socket发送的消息队列 varsocketMsgQueue=[] varsocketOpen=true//判断心跳变量 varheart=''//心跳失败次数 varheartBeatFailCount=0//终止心跳 varheartBeatTimeOut=null;//终止重新连接 varconnectSocketTimeOut=null; Page({ /** *页面的初始数据 */ data:{ sayValue:'', tellData:[],//聊天消息 idx:'', id:'', fjh:'',//房间号 myinputing:'', isSend:'ask', }, /** *生命周期函数--监听页面加载 */ onLoad:function(options){ this.setData({ id:options.id, fjh:options.roomNum, }) this.history(1) this.connectStart() }, /** *生命周期函数--监听页面初次渲染完成 */ onReady:function(){ //监听websocket连接状态 this.deal() }, /** *生命周期函数--监听页面显示 */ onShow:function(){ console.log() }, /** *生命周期函数--监听页面隐藏 */ onHide:function(){ }, /** *生命周期函数--监听页面卸载 */ onUnload:function(){ varthat=this //离开页面销毁websocket并恢复初始数据 wx.closeSocket() twice=0 socketOpen=true heart=''//心跳失败次数 heartBeatFailCount=0//终止心跳 heartBeatTimeOut=null;//终止重新连接 connectSocketTimeOut=null; }, /** *页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh:function(){ }, /** *页面上拉触底事件的处理函数 */ onReachBottom:function(){ }, /** *用户点击右上角分享 */ onShareAppMessage:function(){ console.log('点击分享') }, //获取聊天室历史记录 history:function(a){ varthat=this wx.request({ url:server+'api/message/chatmsg', header:{ "Authorization":app.globalData.token, }, data:{ page:a, type:'', resultsPerPage:1000, stream:that.data.id }, success:(res)=>{ varh=res.data.data.items if(h.length>0){ varmyArr=[] varc=0 h.forEach(i=>{ c++ i.id=c if(i.type=='question'||i.type=='answer'){ i.content=JSON.parse(i.content) } myArr.push(i) }) varj=h.length-1 varidx=h[j].id //console.log(h,idx) that.setData({ tellData:h, idx:idx, }) } } }) }, //与socket建立连接 connectStart:function(){ varthat=this ws=wx.connectSocket({ url:myurl, header:{ "Authorization":app.globalData.token, 'content-type':'application/json' }, data:JSON.stringify({ token:app.globalData.token, type:3, payLoad:{ topic:that.data.fjh } }), success:(res)=>{ //console.log("进入聊天",res) }, fail:(err)=>{ wx.showToast({ title:'网络异常!', }) console.log(err) }, }) //连接成功 wx.onSocketOpen((res)=>{ console.log('WebSocket成功连接',res) that.resMes() //开始心跳 that.startHeartBeat() }) //连接失败 wx.onSocketError((err)=>{ console.log('websocket连接失败',err); twice=0 that.connectStart() }) }, //开始心跳 startHeartBeat:function(){ //console.log('socket开始心跳') varthat=this; heart='heart'; that.heartBeat(); }, //心跳检测 heartBeat:function(){ varthat=this; if(!heart){ return; } varxtData={ token:app.globalData.token, type:1, payLoad:"" } //console.log(JSON.stringify({xtData})) that.sendSocketMessage({ msg:JSON.stringify(xtData), data:JSON.stringify(xtData), success:function(res){ //console.log('socket心跳成功',res); if(heart){ heartBeatTimeOut=setTimeout(()=>{ that.heartBeat(); },5000); } }, fail:function(res){ console.log('socket心跳失败'); if(heartBeatFailCount>2){ //重连 console.log('socket心跳失败') that.connectStart(); } if(heart){ heartBeatTimeOut=setTimeout(()=>{ that.heartBeat(); },5000); } heartBeatFailCount++; }, }); }, //进入聊天 resMes:function(){ varthat=this varjoinData={ token:app.globalData.token, type:3, payLoad:JSON.stringify({ topic:that.data.fjh }), } //console.log(joinData) that.sendSocketMessage({ msg:JSON.stringify(joinData), data:JSON.stringify(joinData), success:function(res){ //console.log('进入房间成功',res); that.deal() }, fail:function(err){ console.log('进入房间失败'); }, }) }, //结束心跳 stopHeartBeat:function(){ //console.log('socket结束心跳') varthat=this; heart=''; if(heartBeatTimeOut){ clearTimeout(heartBeatTimeOut); heartBeatTimeOut=null; } if(connectSocketTimeOut){ clearTimeout(connectSocketTimeOut); connectSocketTimeOut=null; } }, //消息发送 foo:function(){ if(this.data.inputValue){ //DoSomething }else{ //CatchError } this.setData({ inputValue:''//将data的inputValue清空 }); return; }, sayValue:function(e){ varthat=this //console.log(this.data.isSend) if(that.data.isSend=='ask'){ that.setData({ isSend:'send' }) } that.setData({ sayValue:e.detail.value }) }, sendMes:function(e){ varthat=this //console.log(this.data.sayValue,111) varmyInput=this.data.sayValue vartoken=app.globalData.token if(that.data.isSend=='sureAsk'){ wx.request({ url:server+'api/question/add', method:'POST', header:{ "Authorization":app.globalData.token, 'content-type':'application/json' }, data:{ content:myInput, streamId:that.data.id }, success:(res)=>{ console.log(res,'我的提问') } }) }else{ //console.log(app.globalData.userInfo) varchatInfo={ user:app.globalData.userInfo.id, displayName:app.globalData.userInfo.displayName, avatarurl:app.globalData.userInfo.avatarUrl, stream:that.data.id, content:myInput, type:"message", createdat:"2018-10-814:30" } varsendData={ token:token, type:2, payLoad:JSON.stringify({ topic:that.data.fjh, chatInfo:JSON.stringify(chatInfo) }) } //console.log(JSON.stringify(sendData)) that.sendSocketMessage({ msg:JSON.stringify(sendData) }) } that.setData({ sayValue:'', isSend:'ask' }) }, //通过WebSocket连接发送数据 sendSocketMessage:function(options){ varthat=this if(socketOpen){ wx.sendSocketMessage({ data:options.msg, success:function(res){ if(options){ options.success&&options.success(res); } }, fail:function(res){ if(options){ options.fail&&options.fail(res); } } }) }else{ socketMsgQueue.push(options.msg) } //ws.closeSocket(); //that.deal() }, //监听socket deal:function(){ varthat=this ws.onOpen(res=>{ socketOpen=true; console.log('监听WebSocket连接打开事件。',res) }) ws.onClose(onClose=>{ console.log('监听WebSocket连接关闭事件。',onClose) //socketOpen=false; //that.connectStart() }) ws.onError(onError=>{ console.log('监听WebSocket错误。错误信息',onError) socketOpen=false }) ws.onMessage(onMessage=>{ varres=JSON.parse(onMessage.data) //console.log(res,"接收到了消息") if(res.code==200){ //console.log('服务器返回的消息',res.data) varresData=JSON.parse(res.data) vararr=that.data.tellData resData.id=arr.length+1 if(resData.type=='question'||resData.type=='answer'){ resData.content=JSON.parse(resData.content) console.log('这是提问',resData.type,resData.content.content) } arr.push(resData) console.log(resData,arr.length) that.setData({ tellData:arr, idx:resData.id }) }else{ } }) }, time:function(a){ vardata=newDate(a) varyear=data.getFullYear(); varmonth=data.getMonth()+1; varday1=data.getDate(); varhh=data.getHours();//截取小时 varmm=data.getMinutes();//截取分钟 if(month<10){ month='0'+month } if(day1<10){ day1='0'+day1 } if(hh<10){ hh='0'+hh } if(mm<10){ mm='0'+mm } varnewday=month+"月"+day1+''+hh+':'+mm returnnewday }, inputing:function(){ console.log('获取焦点') this.setData({ isSend:'send' }) }, inputed:function(){ //console.log('失去焦点') this.setData({ isSend:'ask', }) }, ask:function(){ //console.log('提问') this.setData({ myinputing:true, isSend:'sureAsk' }) }, })
以上仅是前端部分本人小程序websocket的使用实例,具体的情况需要配合自己的服务端。希望对大家有所帮助,也欢迎大家互相讨论。