You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
5.1 KiB
202 lines
5.1 KiB
|
|
class Ws {
|
|
constructor(ws, data, ...args) { // [{url, data, method...},,,,]
|
|
this._ws = ws;
|
|
this._data = data;
|
|
// 待发送的消息列
|
|
this._msgs = []
|
|
|
|
this.socket = this.doLink();
|
|
this.doOpen();
|
|
// 订阅/发布模型
|
|
this._events = {};
|
|
// 是否保持连接
|
|
this._isLink = true;
|
|
// 订阅列表(交易所专用)
|
|
this.subs = []
|
|
// 循环检查
|
|
this.linkCounter = 0;
|
|
setInterval(() => {
|
|
if (this._isLink && this.linkCounter < 8) {
|
|
this.linkCounter++;
|
|
if (this.socket.readyState == 2 || this.socket.readyState == 3) {
|
|
this.resetLink()
|
|
}
|
|
}
|
|
}, 3000)
|
|
}
|
|
// 重连
|
|
resetLink() {
|
|
this.socket = this.doLink(() => {
|
|
this.Notify({
|
|
Event: 'resetLink'
|
|
});
|
|
this.resetSub()
|
|
});
|
|
this.doOpen();
|
|
}
|
|
// 连接
|
|
doLink(call) {
|
|
let ws = uni.connectSocket({
|
|
url: this._ws,
|
|
// 可选参数 设置默认值
|
|
header: {
|
|
'content-type': 'application/json'
|
|
},
|
|
method: 'GET',
|
|
success: () => {
|
|
call && call()
|
|
}
|
|
})
|
|
return ws;
|
|
}
|
|
doOpen() {
|
|
this.socket.onOpen((ev) => {
|
|
this.onOpen(ev)
|
|
})
|
|
this.socket.onMessage((ev) => {
|
|
this.onMessage(ev)
|
|
})
|
|
this.socket.onClose((ev) => {
|
|
this.onClose(ev)
|
|
})
|
|
this.socket.onError((ev) => {
|
|
this.onError(ev)
|
|
})
|
|
|
|
}
|
|
// 打开
|
|
onOpen() {
|
|
// 打开时重发未发出的消息
|
|
let list = Object.assign([], this._msgs)
|
|
list.forEach((item) => {
|
|
if (this.send(item)) {
|
|
let idx = this._msgs.indexOf(item)
|
|
if (idx != -1) {
|
|
this._msgs.splice(idx, 1)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
// 手动关闭
|
|
doClose() {
|
|
this._isLink = false
|
|
this._events = {}
|
|
this._msgs = []
|
|
this.socket.close({
|
|
success: () => {
|
|
console.log('socket close success')
|
|
}
|
|
})
|
|
}
|
|
// 添加监听
|
|
on(name, handler) {
|
|
this.subscribe(name, handler);
|
|
}
|
|
// 取消监听
|
|
off(name, handler) {
|
|
this.unsubscribe(name, handler);
|
|
}
|
|
// 关闭事件
|
|
onClose() {
|
|
// 是否重新连接
|
|
if (this._isLink && this.linkCounter < 8) {
|
|
setTimeout(() => {
|
|
this.resetLink()
|
|
}, 3000)
|
|
}
|
|
}
|
|
// 错误
|
|
onError(evt) {
|
|
this.Notify({
|
|
Event: 'error',
|
|
Data: evt
|
|
});
|
|
|
|
}
|
|
// 接受数据
|
|
onMessage(evt) {
|
|
try {
|
|
|
|
// 解析推送的数据
|
|
const data = JSON.parse(evt.data);
|
|
|
|
// 通知订阅者
|
|
this.Notify({
|
|
Event: 'message',
|
|
Data: data
|
|
});
|
|
|
|
} catch (err) {
|
|
console.error(' >> Data parsing error:', err);
|
|
// 通知订阅者
|
|
this.Notify({
|
|
Event: 'error',
|
|
Data: err
|
|
});
|
|
}
|
|
}
|
|
// 订阅事件的方法
|
|
subscribe(name, handler) {
|
|
if (this._events.hasOwnProperty(name)) {
|
|
this._events[name].push(handler); // 追加事件
|
|
} else {
|
|
this._events[name] = [handler]; // 添加事件
|
|
}
|
|
}
|
|
// 取消订阅事件
|
|
unsubscribe(name, handler) {
|
|
let start = this._events[name].findIndex(item => item === handler);
|
|
// 删除该事件
|
|
this._events[name].splice(start, 1);
|
|
}
|
|
// 发布后通知订阅者
|
|
Notify(entry) {
|
|
// 检查是否有订阅者 返回队列
|
|
const cbQueue = this._events[entry.Event];
|
|
if (cbQueue && cbQueue.length) {
|
|
for (let callback of cbQueue) {
|
|
if (callback instanceof Function) callback(entry.Data);
|
|
}
|
|
}
|
|
}
|
|
// 发送消息
|
|
send(data) {
|
|
this.changeSubs(data)
|
|
if (this.socket.readyState == 1) {
|
|
this.socket.send({ data: JSON.stringify(data) })
|
|
return true
|
|
} else {
|
|
// 保存到待发送信息
|
|
if (!this._msgs.includes(data)) {
|
|
this._msgs.push(data)
|
|
};
|
|
return false
|
|
}
|
|
|
|
}
|
|
// 修改订阅列表(交易所用)
|
|
changeSubs(data) {
|
|
if (data.cmd == 'sub') {
|
|
if (!this.subs.includes(data.msg)) {
|
|
this.subs.push(data.msg)
|
|
}
|
|
} else if (data.cmd == 'unsub') {
|
|
let idx = this.subs.indexOf(data.msg)
|
|
if (idx != -1) {
|
|
this.subs.splice(idx, 1)
|
|
}
|
|
}
|
|
}
|
|
// 重新订阅(交易所用)
|
|
resetSub() {
|
|
let list = Object.assign([], this.subs)
|
|
list.forEach((item) => {
|
|
this.send({
|
|
cmd: 'sub',
|
|
msg: item
|
|
})
|
|
})
|
|
}
|
|
}
|
|
export default Ws
|