262 lines
5.8 KiB
JavaScript
262 lines
5.8 KiB
JavaScript
const noop = function() {};
|
|
class Socket {
|
|
static stopTime = 0;
|
|
static concatCount = 0;
|
|
constructor({
|
|
url = '',
|
|
onOpen = noop,
|
|
onMsg = noop,
|
|
onClose = noop,
|
|
onError = noop,
|
|
onReload = noop,
|
|
onRdFinsh = noop,
|
|
maxInterValCount = 10,
|
|
interValTime = 2000,
|
|
SocketState = {},
|
|
...args
|
|
} = {}) {
|
|
this.isRconnectIng = false; //是否处于重连状态
|
|
this.waiting = Promise.resolve(false); //心跳检查必须等待重连完成后
|
|
this.waitDep = []; //等待时收集依赖的容器
|
|
this.SocketTask = {
|
|
nsend: noop,
|
|
nclose: noop,
|
|
nrconnect: noop,
|
|
isconnect: false,
|
|
uniColse: false,
|
|
maxInterValCount,
|
|
interValTime,
|
|
InterValCount: 0,
|
|
eventPatch: null,
|
|
url,
|
|
onOpen,
|
|
onMsg,
|
|
onClose,
|
|
onError,
|
|
onReload,
|
|
onRdFinsh,
|
|
extra: args
|
|
};
|
|
this._EventDispath(this.SocketTask);
|
|
//this.initChat(this.SocketTask, this.SocketTask.extra);
|
|
return this.SocketTask;
|
|
|
|
}
|
|
set CONCATCOUNT(value) {
|
|
Socket.concatCount = value;
|
|
if (value > 0) this._notify();
|
|
}
|
|
get CONCATCOUNT() {
|
|
return Socket.concatCount
|
|
}
|
|
/**
|
|
* 仅供内部使用,通知所有收集到的依赖
|
|
*/
|
|
_notify() {
|
|
for (let i = 0; i < this.waitDep.length; i++) {
|
|
this.waitDep[i].call(this.SocketTask);
|
|
}
|
|
this.waitDep = [];
|
|
}
|
|
/**
|
|
* 仅供内部使用,确认当前是否连接成功,收集依赖
|
|
*/
|
|
_chunkConnect(fn) {
|
|
if (Socket.concatCount > 0) {
|
|
fn();
|
|
} else {
|
|
this.waitDep.push(fn);
|
|
}
|
|
}
|
|
/**
|
|
* 仅供内部使用,事件注册
|
|
*/
|
|
_EventDispath({
|
|
onReload
|
|
} = {}) {
|
|
let SocketTask = this.SocketTask;
|
|
let events = {
|
|
onOpen: [],
|
|
onMsg: [],
|
|
onClose: [],
|
|
onError: [],
|
|
onReload: [],
|
|
onRdFinsh: [],
|
|
}
|
|
SocketTask.connectserver = config => {
|
|
//重连,判断是否
|
|
if (!SocketTask.isconnect && !this.isRconnectIng)
|
|
{
|
|
this.SocketTask.url = config.node_site_url
|
|
this.initChat(this.SocketTask, this.SocketTask.extra);
|
|
}
|
|
}
|
|
SocketTask.nsend = msg => {
|
|
let text = JSON.stringify(msg)
|
|
this._chunkConnect(() => {
|
|
uni.sendSocketMessage({
|
|
data: text
|
|
})
|
|
})
|
|
}
|
|
SocketTask.nclose = t => {
|
|
this._chunkConnect(() => {
|
|
SocketTask.uniColse = true;
|
|
uni.closeSocket();
|
|
})
|
|
}
|
|
SocketTask.nrconnect = t => {
|
|
this._chunkConnect(() => {
|
|
this.waiting = new Promise(async (resolve) => {
|
|
uni.closeSocket();
|
|
let reloadStatus = false;
|
|
try {
|
|
const res = await this.initChat(SocketTask, SocketTask.extra);
|
|
reloadStatus = res;
|
|
} catch (e) {}
|
|
onReload.call(SocketTask, reloadStatus, SocketTask);
|
|
SocketTask.eventPatch.dispatchEvent('onReload', reloadStatus);
|
|
resolve(reloadStatus);
|
|
})
|
|
})
|
|
}
|
|
|
|
function EventDispatcher() {
|
|
this.events = events;
|
|
}
|
|
for (let key in events) {
|
|
EventDispatcher.prototype[key] = function(handler) {
|
|
if (typeof handler != 'function') return;
|
|
this.events[key].push(handler)
|
|
}
|
|
}
|
|
EventDispatcher.prototype.dispatchEvent = function(type, msg) {
|
|
let evenArr = this.events[type];
|
|
if (evenArr.length > 0) {
|
|
for (let i = 0; i < evenArr.length; i++) {
|
|
evenArr[i].call(SocketTask, msg, SocketTask);
|
|
}
|
|
}
|
|
}
|
|
SocketTask.eventPatch = new EventDispatcher();
|
|
}
|
|
/**
|
|
* 心跳检测
|
|
*/
|
|
async hbDetection() {
|
|
const SocketTask = this.SocketTask;
|
|
if (SocketTask.uniColse) {
|
|
return false;
|
|
}
|
|
clearTimeout(Socket.stopTime);
|
|
if (!SocketTask.isconnect) { //未连接则启动连接
|
|
if (SocketTask.maxInterValCount > SocketTask.InterValCount) {
|
|
Socket.stopTime = setTimeout(async () => {
|
|
try {
|
|
const R_result = await this.waiting;
|
|
if (R_result) return;
|
|
this.isRconnectIng = true;
|
|
const openResult = await this.initChat(SocketTask, SocketTask.extra);
|
|
if (openResult) return;
|
|
SocketTask.InterValCount++;
|
|
return this.hbDetection();
|
|
} catch (e) {
|
|
return this.hbDetection();
|
|
}
|
|
}, SocketTask.interValTime)
|
|
} else {
|
|
SocketTask.onRdFinsh.call(SocketTask, SocketTask.maxInterValCount, SocketTask);
|
|
SocketTask.eventPatch.dispatchEvent('onRdFinsh', SocketTask.maxInterValCount);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* websocket监听事件
|
|
*/
|
|
SocketEvents({
|
|
onOpen,
|
|
onMsg,
|
|
onClose,
|
|
onError,
|
|
onReload,
|
|
} = {}) {
|
|
return new Promise((resolve, reject) => {
|
|
const SocketTask = this.SocketTask;
|
|
uni.onSocketOpen(res => {
|
|
this.CONCATCOUNT += 1;
|
|
this.isRconnectIng = false;
|
|
SocketTask.isconnect = true;
|
|
SocketTask.InterValCount = 0;
|
|
SocketTask.uniColse = false;
|
|
resolve(true);
|
|
onOpen.call(SocketTask, res, SocketTask);
|
|
SocketTask.eventPatch.dispatchEvent('onOpen', res)
|
|
})
|
|
uni.onSocketMessage(msg => {
|
|
onMsg.call(SocketTask, msg, SocketTask);
|
|
SocketTask.eventPatch.dispatchEvent('onMsg', msg)
|
|
})
|
|
uni.onSocketClose(async err => {
|
|
SocketTask.isconnect = false;
|
|
resolve(false);
|
|
if (!this.isRconnectIng) {
|
|
this.hbDetection();
|
|
onClose.call(SocketTask, err, SocketTask);
|
|
SocketTask.eventPatch.dispatchEvent('onClose', err);
|
|
}
|
|
})
|
|
uni.onSocketError(err => {
|
|
uni.closeSocket();
|
|
onError.call(SocketTask, err, SocketTask);
|
|
SocketTask.eventPatch.dispatchEvent('onError', err)
|
|
})
|
|
})
|
|
}
|
|
/**
|
|
* 开始初始化chat
|
|
*/
|
|
initChat({
|
|
url,
|
|
onOpen,
|
|
onMsg,
|
|
onClose,
|
|
onError,
|
|
onReload
|
|
} = {}, args) {
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
await this.connectSocket(url, args);
|
|
let res = await this.SocketEvents({
|
|
onOpen,
|
|
onMsg,
|
|
onClose,
|
|
onError,
|
|
onReload,
|
|
})
|
|
resolve(res);
|
|
} catch (e) {
|
|
console.log(e)
|
|
reject();
|
|
}
|
|
})
|
|
}
|
|
/**
|
|
* 连接webSocket
|
|
*/
|
|
connectSocket(url, args) {
|
|
return new Promise((resolve, reject) => {
|
|
uni.connectSocket({
|
|
url,
|
|
success: () => {
|
|
resolve();
|
|
},
|
|
fail: err => {
|
|
reject();
|
|
},
|
|
...args
|
|
})
|
|
})
|
|
}
|
|
}
|
|
export default Socket
|