大家都知道,小程序的websocket在切入后台5秒左右,会断开链接,或者长时间无数据收发,也会切断链接。
然而心跳数据并不能完全保证链接的正常,
我在这里说一下我的经验,我初中毕业(真的),代码方面写的不好不要见笑。
首先,我为了知道当前的网络是否断了,使用了一个标志位比如 :
var NetworkIsOK = false;
当首次链接打开时比如socket的 onOpen 事件!在这个事件回调中,将NetworkIsOK = true;
同理,如果网络出现错误,在错误的回调中将NetworkIsOK = false;
建立一个发送 发送区数据 暂存站
var SendBuffer =[];
将socket的send 函数包装一下,比如取名SendToServer(data)
在SendToServer中,首先检查网络的状态,如果状态是正常的,则直接调用socket.send()发送数据,
如果不是正常的,则重新链接服务器,并在onOpen事件中检查 SendBuffer.length是否大于 0 ,如果有存入的缓冲数据,则依次发送掉,
以下是部分实际代码,请忽略我垃圾的编程水平!
var app = getApp(); /** * 与服务器进行通信的所有操作在此进行 */ var Server = {}; Server.socket = null ; //socket连接句柄 Server.isOK = false ; //服务器连接状态处理数组 Server.event = []; //事件注册处理数组 Server.url = 'wss://********' ; //服务器地址 Server.SendBuffer=[]; //数据包发送缓冲 /** * 初始化操作 */ Server.Init= function (apps){ console.log( 'hello server' ); app = apps; console.log(app); var Timer; /**执行服务器连接逻辑 */ Server.socket = wx.connectSocket({ url:Server.url }); //132.232.87.229 Server.socket.onOpen( function () { console.log( 'Server open' ); Server.isOK= true ; //可以通信了 //显示成功 wx.showToast({ title: '已连接服务器 ' , }); Timer = setInterval( function () { Server.startHeart(); }, 1000 * 50); }); Server.socket.onError( function () { console.log( 'Server error' ); Server.isOK = false ; //显示成功 wx.showToast({ title: '服务器连接错误' , icon: 'none' }); //Server.reLink(); clearInterval(Timer); }); Server.socket.onClose( function () { console.log( 'Server close' ); Server.isOK = false ; //显示成功 wx.showToast({ title: '服务器连接关闭' , icon: 'none' }); //Server.reLink(); clearInterval(Timer); }); Server.socket.onMessage( function (res) { //Server.socketPress.onMessage(res); var message = JSON.parse(res.data); if (!message) return ; //空数据 var Operator = message.Operator; var event=Server.event[Operator]; if (event){ event(message); //实际执行 } });
Server.reLink= function (){ var Timer; /**执行服务器连接逻辑 */ Server.socket = wx.connectSocket({ url:Server.url }); //132.232.87.229 Server.socket.onOpen( function () { console.log( 'Server open' ); Server.isOK = true ; //可以通信了 //显示成功 wx.showToast({ title: '已连接服务器 ' , }); Server.Login(); //重新注册登入 Timer = setInterval( function (){ Server.startHeart(); },1000*50); //检查缓冲区是否有未发送数据 while (Server.SendBuffer.length>0){ var data = Server.SendBuffer.pop(); //将用户的code发往服务器 Server.socket.send({ data: data }); console.log( '将缓存中的信息发送' ,data) } }); Server.socket.onError( function () { console.log( 'Server error' ); Server.isOK = false ; //显示成功 wx.showToast({ title: '服务器连接错误' , icon: 'none' }); //Server.reLink(); clearInterval(Timer); }); Server.socket.onClose( function () { console.log( 'Server close' ); Server.isOK = false ; //显示成功 wx.showToast({ title: '服务器连接关闭' , icon: 'none' }); //Server.reLink(); clearInterval(Timer); }); Server.socket.onMessage( function (res) { //Server.socketPress.onMessage(res); var message = JSON.parse(res.data); if (!message) return ; //空数据 var Operator = message.Operator; var event = Server.event[Operator]; if (event) { event(message); //实际执行 } }); }; /** * 启动心跳 */ Server.startHeart= function (){ if (Server.isOK == false ) { Server.reLink(); //重连 return ; } var sendData = { Operator: 'Heart' , //操作方式 }; var JsonData = JSON.stringify(sendData); // console.log(JsonData); //将用户的code发往服务器 Server.socket.send({ data: JsonData }); Server.addEvent( 'HeartOK' , function (message){ // console.log('心跳OK',message); }) } /**用户登陆 */ Server.Login= function (ques){ var userOpenId = wx.getStorageSync( 'openId' ); console.log(app); var sendData = { Operator: 'userLogin' , //操作方式 userCode: app.userCode, //用户code userInfo: app.userInfo, //用户信息 }; if (userOpenId) { //如果缓存中的有效,就用缓存中的openId发过去给服务器 sendData.userOpenId = userOpenId; console.log( '调用缓存openID' ); } var JsonData = JSON.stringify(sendData); console.log( "登陆数据:" , JsonData); // console.log(JsonData); //将用户的code发往服务器 Server.SendData(sendData); /**如果是黑名单用户,禁止使用 */ Server.addEvent( 'BanLogin' , function (message){ if (ques) { ques(); } }); }; /** * 注册消息执行处理函数 */ Server.addEvent= function (eventName,eventHandle){ Server.event[eventName] = eventHandle; } /**注册登入成功处理事件 */ Server.addEvent( 'LoginOK' , function (message){ console.log( 'LOGIN OK' ); console.log(message); wx.setStorageSync( 'openId' ,message.openId); }); /**注册登入失败处理事件 */ Server.addEvent( 'LoginError' , function (message) { wx.showModal({ content: '登入失败了!部分功能可能无法使用,可能是网络原因,也可能是没有获得授权' , showCancel: false , success: function (res) { if (res.confirm) { //console.log('用户点确定'); } } }); }); /** * 创建帖子 */ Server.CreateInvitation= function (table,image,text,isRichText){ var sendData = { Operator: 'CreateInvitation' , //操作方式 isRichText:isRichText, //是否为富文本 Table:table, //标题 Image:image, //图片地址 Text:text, //文本内容 }; Server.SendData(sendData); }; /** * 从服务器获取贴子 */ Server.GetInvitation= function (id,mode,time,limt,skip,success){ var sendData = { Operator: 'GetInvitation' , //操作方式 id:id, //使用帖子ID的查询方式 mode:mode, //操作模式 time:time, //时间查询时使用的时间 limt:limt, //分页查询时需要获取的贴子数量 skip:skip, //需要跳过的帖子数量 }; //var JsonData = JSON.stringify(sendData); Server.SendData(sendData); /**注册登入成功处理事件 */ Server.addEvent( 'GetInvitationOK' , function (message) { console.log( 'GetInvitationOK' ); var data = message.data; var serverTime=message.serverTime; if (success) success(data,serverTime); //回调执行 }); } /** * 创建帖子评论 */ Server.CreateInvitationComment= function (_id,text,success){ var sendData = { Operator: 'CreateInvitationComment' , //操作方式 id:_id, //使用帖子ID的查询方式 text:text, //评论内容 }; Server.SendData(sendData); /**注册登入成功处理事件 */ Server.addEvent( 'CreateInvitationCommentOK' , function (message) { console.log( 'CreateInvitationCommentOK' ); var data = message.data; if (success) success(data); //回调执行 }); }; /** * 给帖子点赞 */ Server.LoveInvitation= function (_id,success){ var sendData = { Operator: 'LoveInvitation' , //操作方式 id:_id, //使用帖子ID的查询方式 }; Server.SendData(sendData); /**注册登入成功处理事件 */ Server.addEvent( 'LoveInvitationOK' , function (message) { console.log( 'LoveInvitationOK' ); if (success) success(); //回调执行 }); } /** * 向服务器发送数据,数据类型为任意数据, * 如果服务器断线,则自动重连服务器,数据被暂存,重连成功后将被发送 */ Server.SendData= function (data){ if (Server.isOK == false ) { Server.reLink(); //重连 //将未发送数据存入Buffer var JsonData = JSON.stringify(data); Server.SendBuffer.push(JsonData); return ; } else { //否则直接给服务器发送数据 var JsonData = JSON.stringify(data); Server.socket.send({ data: JsonData }); } } //暴露接口 module.exports.Server = Server; |
这个切入点很好,不过,可以事先阐述一下你的方案是什么,已经解决的问题是啥?这样后面的读者能更好的了解你的文章目的。
推荐下次 可以将代码 拆分为一段一段来讲,其实,分享也是一种学习方式。
学历是社会给你的标签,不是你自己给你的标签。
加油。
嗯,我的想法很简单,就是保证数据都能被有效的发送,所以整了这么个, 就目前的使用来看效果比较好,即使断线了出错了,只要一有数据发送,就能重新连接,然后发送数据, 因为是直接复制的项目代码,所以里面还有消息的处理方式,看起来不够简单
有没有wss域名搭建的教程啊 求分享
还行 后台也做过websocket,对长连接更加深入,代码还有很多优化的余地,es5的写法比较多,距离老司机还有点距离
~是吗,忘大神指教。我是刚学的javascript~
刚学的就会这些了 厉害