### 前言
传统http短连接拉取接收数据太浪费资源,tcp每次都得建立连接,三次握手,释放,只能单向通信,定时轮询。
而websocket可以建立长连接,后一直保持,节约服务器资源,跟每台客户机只维持一个连接就行。
节省流量 不需要频繁地发起关闭tcp连接,可以双向通信,
协议以及数据格式自己算了算,浏览器、app、物联网多种设备一套接口通用,省略HTTP上不多余的信息,
基于以上原因,开发一套socket框架来代替http ajax模式,同时保持跟http一样容易上手
### 目的
用websocket实现Ajax回调效果,所有接口请求用websocket进行,
想要使websocket发送的消息实现跟ajax回调消息那种效果,发送出去,然后回调函数里收到服务器发送来的消息
### 难点
websocket与http不同的之处在于,http发的请求是同步的,浏览器发起请求会同步等待服务器返回,而socket是发送完了就结束了,不管服务器又没返回,而且先发地数据不一定先收到,不按顺序返回,
难点就在于发送数据在ws.send函数里,而接收数据在ws.onmessage里,数据不能互通
### 原理
解决方法
发送消息的时候把回调函数存到一个数组中,数组下标用唯一键名避免冲突,键名要发送给服务器,服务器返回数据的时候要带上,
收到服务器消息时,取出键名去调用数组中对应的回调函数,把数据传入回调函数执行回调操作
这样就实现了跟ajax一样的效果
### 实现
代码示例
socket.js
`
//websocket地址
let host = "ws://localhost:8282";
let ws = null;
let socketOpen = false;
let callbackArr = [];
let msgArr = [];
//心跳时间
let heartCheckTime = 45000;
//重连尝试次数
let reconnectTime = 0;
function wsConnect() {
ws = new WebSocket(host);
// 打开socket连接
ws.onopen = e => {
socketOpen = true;
console.log('连接成功');
//待发送消息队列
if (msgArr.length) {
for (let i in msgArr) {
sendMsg(msgArr[i].data, msgArr[i].callback)
}
msgArr = []
}
// 心跳
heartCheck()
};
// socketClose
ws.onclose = e => {
console.log('连接已断开', e);
socketOpen = false;
reconnect();
};
//连接发生错误
ws.onerror = e => {
console.log('连接发生错误', e);
socketOpen = true;
reconnect();
};
//接收消息
ws.onmessage = e => {
// 按api保存回调
let callBackData = JSON.parse(e.data);
let key = callBackData.key;
if (!key) return;
callbackArr[key](callBackData)
}
}
// 发送消息
function send(data, callback) {
callbackArr[data.key] = callback
// console.log('发送消息',data)
if (socketOpen) {
ws.send(JSON.stringify(data))
} else {
// 未开启,加入队列
msgArr.push({data, callback});
wsConnect();
}
}
// 心跳检测
function heartCheck() {
if (socketOpen) {
setInterval(() => {
ws.send('ping')
console.log("发送ping", heartCheckTime)
}, heartCheckTime);
}
}
// 重连
function reconnect() {
if (!socketOpen && reconnectTime <= 10) {
setTimeout(() => {
wsConnect()
reconnectTime++
console.log('重新连接', reconnectTime)
}, 2000)
}
}
module.exports.send = send
`