场景
将websocket实例以及包含的方法封装为ws.js,方便调用。无论是原生h5开发还是现代框架vue开发都可以使用。很多地方经常需要进行长连接进行异步任务,所以websocket是个十分不错的方式。(导入,导出,报警事件推送等等)
效果(实际运行浏览器截图)
ws.js代码
/**
* 使用方法
* 1、连接某个 websocket
*/
//在这ws
let wsOnMessage = []
let wsOnMessages = []
let wsOnOpen = []
let wsStatus = []
let websocket = {
url: undefined,
instance: undefined,//实例
userId: undefined,
evts:undefined,
notReOpen:undefined,
wsStatus: undefined,//状态
wsInitialId: undefined,//最初的Id
wsSessionId: undefined,
wsBreakLinkNum: 0, // 断开重连次数
async open (url, userId, evts) {
if (websocket.instance) return
websocket.url = url
websocket.userId = userId
websocket.evts = evts||"['help']"
websocket.instance = new WebSocket(websocket.url)
websocket.instance.addEventListener('open', websocket.WSOpen)
websocket.instance.onmessage = websocket.WSMessage
websocket.instance.addEventListener('close', websocket.WSClose)
},
WSOpen (e) {
// Subscribe 事件类型:订阅事件
websocket.instance.send(`{
"eventType":"Subscribe",
"evts":["help"],
"sessionId":"${window.localStorage.sessionId}",
"userId": "${window.localStorage.employeeId||'1'}",
"centreId":"${window.localStorage.serviceCenterId||'1'}"
}`)
wsOnOpen.forEach(item => {
item.callback(websocket.instance)
})
},
WSMessage (e) {
if (!e.data) return
let data = JSON.parse(e.data)
// if (!data.data) return
if (data.code === 200) {
//重置 wsInitialId
if (!websocket.wsInitialId || websocket.wsSessionId !== data.data.wsSessionId) {
websocket.wsInitialId = websocket.wsSessionId
}
websocket.wsSessionId = data.wsSessionId
websocket.wsStatus = '已连接'
} else {
websocket.wsStatus = data.msg
}
wsOnMessage.forEach(item => {
item.callback(data, websocket.instance)
})
},
// 断线重连
WSClose (e) {
console.log('执行WSClose')
websocket.wsStatus = '已断开连接'
websocket.wsBreakLinkNum++
wsStatus.forEach(item => {
item.callback({
wsStatus: websocket.wsStatus,
wsInitialId: websocket.wsInitialId,
wsSessionId: websocket.wsSessionId,
wsBreakLinkNum: websocket.wsBreakLinkNum
}, websocket.instance)
})
console.log(
`%c websocket %c 断线了`,
'background:#35495e;padding:1px;border-radius:3px 0 0 3px;color:#FFF',
'background:#41b883;padding:1px;border-radius:0 3px 3px 0;color:#FFF'
)
console.log(websocket.notReOpen)
if (!websocket.instance || websocket.notReOpen) return
//关闭连接ny
websocket.instance.close()
console.log(websocket.instance)
//手动释放ny
websocket.instance = undefined
//定时重连ny
setTimeout(() => {
console.log('试图重连', websocket.url)
websocket.open(websocket.url, websocket.userId,websocket.evts)
}, 2000)
},
//检查心跳 默认30s ping 一次,检测是否保持连接
async send (params) {
if (!websocket.instance) return
// var evts = JSON.parse(websocket.evts)
if(params){
websocket.instance.send(`{
"eventType":${params.eventType},
"sessionId":"${window.localStorage.sessionId}",
"userId": "${websocket.userId}"
}`)
}else{
websocket.instance.send(`{
"eventType":"Ping",
"evts":["help"],
"sessionId":"${window.localStorage.sessionId}",
"userId": "${websocket.userId}"
}`)
}
},
onMessage (cmd, callback) {
let hasSame = wsOnMessage.find(item => item.cmd === cmd)
if (hasSame) return // 不许重复绑定事件监听
wsOnMessage.push({
cmd: cmd,
callback: callback
})
},
onStatus (cmd, callback) {
let hasSame = wsStatus.find(item => item.cmd === cmd)
if (hasSame) return // 不许重复绑定事件监听
wsStatus.push({
cmd: cmd,
callback: callback
})
},
offMessage (cmd, callback) {
if (callback) {
let that = wsOnMessage.find(item => item.callback === callback && item.cmd === cmd)
if (!that) return
let index = wsOnMessage.indexOf(that)
wsOnMessage.splice(index, 1)
} else {
let those = wsOnMessage.filter(item => item.cmd === cmd)
those.forEach(item => {
let index = wsOnMessage.indexOf(item)
wsOnMessage.splice(index, 1)
})
}
},
offStatus (cmd, callback) {
if (callback) {
let that = wsStatus.find(item => item.callback === callback && item.cmd === cmd)
if (!that) return
let index = wsStatus.indexOf(that)
wsStatus.splice(index, 1)
} else {
let those = wsStatus.filter(item => item.cmd === cmd)
those.forEach(item => {
let index = wsStatus.indexOf(item)
wsStatus.splice(index, 1)
})
}
},
onOpen (cmd, callback) {
let hasSame = wsOnOpen.find(item => item.callback === callback)
if (hasSame) return // 不许重复绑定事件监听
wsOnOpen.push({
cmd: cmd,
callback: callback
})
},
offOpen (cmd, callback) {
if (callback) {
let that = wsOnOpen.find(item => item.callback === callback && item.cmd === cmd)
if (!that) return
let index = wsOnOpen.indexOf(that)
wsOnOpen.splice(index, 1)
} else {
let those = wsOnOpen.filter(item => item.cmd === cmd)
those.forEach(item => {
let index = wsOnOpen.indexOf(item)
wsOnOpen.splice(index, 1)
})
}
},
close () {
websocket.notReOpen = true
if (!websocket.instance) return
websocket.instance.close()
},
ReOpen (){
websocket.notReOpen = false
}
}
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Game1 Test Demo</title>
</head>
<body>
<div id="mess">正在连接...</div>
<div>
<button id="state1" >发送</button>
<a> 已发送:</a>
<a id="sendnews"></a><br>
<a>已接收:</a>
<a id="receivenews"></a>
</div>
<script src="./ws.js"></script>
<script>
var mess = document.getElementById("mess");
if(window.WebSocket){
//这里修改为本机IP地址 一进页面就进行连接 并且触发心跳 5秒发送一次心跳,心跳这个事可以与后端约定好格式
websocket.open('ws://127.0.0.1:8888', '111222')
//心跳
let timer = null
function Ping () {
clearTimeout(timer)
timer = setTimeout(() => {
let objInput={
eventType:'Ping',
}
websocket.send(objInput)
Ping()
}, 5000)
}
Ping()
}
</script>
</body>
</html>