ws.js
const eventMap = new Map()
const serviceMap = new Map()
const event = {
onopen: [],
onmessage: [],
onclose: [],
onerror: []
}
export class SocketService {
socketInstance = null
initOpt = null
timer = null
reconnecTime = 1000 * 5
lockReconnect = false
constructor({ url, params, ...rest }) {
this.initOpt = { url, params, ...rest }
try {
this.socketInstance = new WebSocket(url)
SocketService.collectEvent(this.initOpt, this, true)
Object.keys(event).forEach((key) => {
const funList = eventMap.has(url) && eventMap.get(url)[key]
this.socketInstance[key] = (e) => {
if (e.type == 'message') {
// 统一处理消息数据
e = e.data
} else if (['onclose', 'onerror'].includes(key)) {
// 关闭或者报错 进行重新连接
console.log(`失败类型:${e.type}`, e)
SocketService.reconnect(this)
}
if (Array.isArray(funList)) {
funList.forEach((fun) => {
if (typeof fun == 'function') fun(e, key)
})
}
}
})
} catch (err) {
console.log('创建socket失败constructor', err)
SocketService.reconnect(this, '初始化')
}
}
send(params) {
if (params) params = JSON.stringify(params)
this.initOpt.params = params
this.socketInstance.send(params)
return this
}
close() {
if (this.socketInstance) {
this.socketInstance.close()
this.socketInstance = null
this.lockReconnect = true
this.timer && clearTimeout(this.timer)
serviceMap.delete(this.initOpt.url)
eventMap.delete(this.initOpt.url)
}
return this
}
static closeAll() {
serviceMap.forEach((i) => {
if (i) i.close()
})
serviceMap.clear()
eventMap.clear()
}
static collectEvent({ url = '', params, ...rest }, serviceInstance, restFlag) {
// 收集事件
if (!eventMap.has(url) || restFlag) eventMap.set(url, JSON.parse(JSON.stringify(event)))
if (params && restFlag) {
// 重新连接 或者 初始化实例 连接成功发送数据
eventMap.get(url)['onopen'].push(() => {
serviceInstance.send(params)
})
}
Object.keys(rest).forEach((key) => {
const lowKey = (key || '').toLowerCase()
if (typeof rest[key] == 'function' && event[lowKey]) {
// 判断是函数 并且是列表里面的函数
eventMap.get(url)[lowKey].push(rest[key])
}
})
if (params && serviceInstance.socketInstance.readyState == 1) {
// 已经初始化 并且有params 发送一次数据
serviceInstance.send(params)
}
}
static reconnect(serviceSelf) {
if (serviceSelf.lockReconnect) {
// 是否已经执行重连
return
}
serviceSelf.lockReconnect = true
//没连接上会一直重连,设置延迟避免请求过多
serviceSelf.timer && clearTimeout(serviceSelf.timer)
serviceSelf.timer = setTimeout(() => {
const socketService = new SocketService(serviceSelf.initOpt)
serviceMap.set(serviceSelf.initOpt.url, socketService)
serviceSelf.lockReconnect = false
}, 5000)
}
}
export const socketRequest = (opt) => {
if (typeof opt.params == 'object' && Object.keys(opt.params).length == 0) opt.params = null
let service = null
if (serviceMap.has(opt.url)) {
service = serviceMap.get(opt.url)
SocketService.collectEvent(opt, service)
} else {
service = new SocketService(opt)
serviceMap.set(opt.url, service)
}
return service
}
配置api
export function SApiMessageNotice(opt = { params: '' }) {
const url = `ws${wsIp}/websocket/${store.state && store.state.userInfo && store.state.userInfo.account}?authToken=${
store.state.authorization
}`;
return socketRequest({
url,
...opt
});
调用api
SApiMessageNotice({
params: {},
onMessage: (res) => {
if (typeof res !== 'string') res = JSON.stringify(res);
notification.open({
message: '消息通知',
description: res,
onClick: () => {
console.log('Notification Clicked!');
}
});
}
});