小程序保持长连接小经验
大家都知道,小程序的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;[代码]