【ES6】websocket封装类(增加重连事件和心跳事件)(适合在vue中使用)
websocket封装对原生的websocket进行改造,但保留原生的事件,只是调用方式不同了代码里面有完整解释下面是源码/*** @author : Jeason Laung* @email: 605251963@qq.com* @date: 2019/1/22**/class socket{/* websocket实例 */ws...
·
websocket封装
对原生的websocket进行改造,但保留原生的事件,只是调用方式不同了
代码里面有完整解释
下面是源码
/*
*
* @author : Jeason Laung
* @date : 2019/1/22
*
*/
class socket{
/* websocket实例 */
ws = null
/*'#'为私有属性,外部不可调用 */
/* 状态 */
//连接状态
#alive = false
//把类的参数传入这里,方便调用
#params = null
/* 计时器 */
//重连计时器
#reconnect_timer = null
//心跳计时器
#heart_timer = null
// 信息onmessage缓存方法
#message_func = null
/* 参数 */
//心跳时间 50秒一次
heartBeat = 50000
//心跳信息:默认为‘hello’随便改,看后台
heartMsg = 'hello'
//是否自动重连
reconnect = true
//重连间隔时间
reconnectTime = 5000
//重连次数
reconnectTimes = 10
constructor(params) {
this.#params = params
this.init()
}
/* 初始化 */
init() {
//重中之重,不然重连的时候会越来越快
clearInterval(this.#reconnect_timer)
clearInterval(this.#heart_timer)
//取出所有参数
let params = this.#params
//设置连接路径
let {url, port} = params
let global_params = ['heartBeat','heartMsg','reconnect','reconnectTime','reconnectTimes']
//定义全局变量
Object.keys(params).forEach(key=>{
if (global_params.indexOf(key) !== -1) {
this[key] = params[key]
}
})
let ws_url = port ? url + ':' + port : url
// this.ws = null
delete this.ws
this.ws = new WebSocket(ws_url)
// window.console.log(this.#message_func)
if (this.#message_func) {
this.onmessage(this.#message_func)
}
//默认绑定事件
this.ws.onopen = () => {
//设置状态为开启
this.#alive = true
clearInterval(this.#reconnect_timer)
//连接后进入心跳状态
this.onheartbeat()
}
this.ws.onclose = () => {
//设置状态为断开
this.#alive = false
clearInterval(this.#heart_timer)
//自动重连开启 + 不在重连状态下
if (true == this.reconnect) {
/* 断开后立刻重连 */
this.onreconnect()
}
}
}
/*
*
* 新增‘心跳事件’和‘重连事件’
*
*/
/* 心跳事件 */
onheartbeat(func) {
//在连接状态下
if (true == this.#alive) {
/* 心跳计时器 */
this.#heart_timer = setInterval(()=>{
//发送心跳信息
this.send(this.heartMsg)
func ? func(this) :false
},this.heartBeat)
}
}
/* 重连事件 */
onreconnect(func) {
/* 重连间隔计时器 */
this.#reconnect_timer = setInterval(()=>{
//限制重连次数
if (this.reconnectTimes <= 0) {
//关闭定时器
// this.#isReconnect = false
clearInterval(this.#reconnect_timer)
//跳出函数之间的循环
return;
}else{
//重连一次-1
this.reconnectTimes--
}
//进入初始状态
this.init()
func ? func(this) : false
},this.reconnectTime)
}
/*
*
* 对原生方法和事件进行封装
*
*/
// 发送消息
send(text) {
if (true == this.#alive) {
text = typeof text == 'string' ? text : JSON.stringify(text)
this.ws.send(text)
}
}
// 断开连接
close() {
if (true == this.#alive) {
this.ws.close()
}
}
//接受消息
onmessage(func,all = false) {
this.ws.onmessage = data => {
this.#message_func = func
func(!all ? data.data : data)
}
}
//websocket连接成功事件
onopen(func) {
this.ws.onopen = event => {
this.#alive = true
func ? func(event) : false
}
}
//websocket关闭事件
onclose(func) {
this.ws.onclose = event => {
//设置状态为断开
this.#alive = false
clearInterval(this.#heart_timer)
//自动重连开启 + 不在重连状态下
if (true == this.reconnect) {
/* 断开后立刻重连 */
this.onreconnect()
}
func ? func(event) : false
}
}
//websocket错误事件
onerror(func) {
this.ws.onerror = event => {
func ? func(event) : false
}
}
}
export default socket
使用
let ws = new socket({
//网址(端口是我下面的服务器的端口)
'url':'ws://127.0.0.1:8001',
//心跳时间(单位:ms)
//'heartBeat':5000,
//发送心跳信息(支持json传入)(这个一般内容不重要,除非后端变态)
//'heartMsg':'hello',
//开起重连
//'reconnect':true,
//重连间隔时间(单位:ms)
//'reconnectTime':5000,
//重连次数
//'reconnectTimes':10
})
//发送信息
ws.send({msg:'你好'})
//关闭连接
ws.close()
//心跳事件
ws.onheartbeat(()=>{
console.log('heartbeat')
})
//心跳事件
ws.onreconnect(()=>{
console.log('reconnect')
})
//接收信息
ws.onmessage((data)=>{
console.log(data)
})
//关闭事件
ws.onclose((event)=>{
console.log(event)
})
//开启事件
ws.onopen((event)=>{
console.log(event)
})
//异常事件
ws.onopen((event)=>{
console.log(event)
})
//更甚至可以直接拿出websocket来用(不推荐)
ws.ws.send('你好')
Vue中使用
在
vue
使用的话我一般把new socket({****})
之后保存在vuex
的state
中,全局方便调用而且可以保留状态
//store.js
import Vue from 'vue';
import Vuex from 'vuex';
//加载文件
import ws from '@/requests/websocket.js'
const socket = new ws({
url:'ws://127.0.0.1:8001',
reconnectTimes:0
})
export default new Vuex.Store({
state: {
'WS':socket
},
mutations: {
},
actions: {
},
});
//App.vue (这个随便你在哪里用反正已经开启的话,到哪里都行)
mounted(){
this.$store.state.WS.message(data=>{
console.log(data)
})
//或者用mapState放在computed中,个人喜欢
}
如果大家缺乏后台,这里提供一个自己写的node搭建的简易websocket服务器
// npm先安装(可以在vue的根目录直接装,把下面的server.js也放到根目录)
npm i nodejs-websocket
复制下面代码保存文件为server.js
放到根目录
我设置了端口为8001
然后在根目录下运行node server.js
,即可
对聊天的更进一步点击这里,这个看后端为主,前端代码可以不用看,之前我自己写的websocket有点别扭
// npm i nodejs-websocket
let ws = require("nodejs-websocket")
let port = 8001
let heart_beat = 60 //每60秒内需要客户端心跳一次,否则关闭连接
let server = ws.createServer(function (conn) {
//计算心跳时间
conn.heart_time = 0
let timer = setInterval(()=>{
//检查心跳时间
if (conn.heart_time > heart_beat) {
clearInterval(timer);
conn.close()
}
conn.heart_time++
},1000)
// function sendOne () {
// conn.sendText
// }
// function sendAll () {
// for ()
// conn.sendText
// }
//根据时间戳生成用户id uid
let uid = String((new Date()).getTime()).slice(-6)
conn.uid = uid
console.log('用户' + uid + ' 已经连接')
// console.log(uid+' is connected')
conn.sendText('Hello man!')
//接受到发过来的信息
conn.on("text", function (text) {
//重置心跳
conn.heart_time = 0
if (text == 'hello') {
//设置的心跳信息,不做任何处理直接返回
return
}
console.log('get user:' + conn.uid + ' message:' + text)
conn.sendText('server get your send:' + text)
})
//断开连接的回调
conn.on("close", function (code, reason) {
console.log('用户' + uid + ' 已经断开连接')
})
//处理错误事件信息
conn.on('error', function (err) {
console.log('用户' + uid + ' 已经断开连接,错误原因: ' + err)
})
}).listen(port);//8001端口
console.log('ws://127.0.0.1:'+port+' is runing.')
请大家尊重原创???
2019-02-21更新
在项目中我发现调用的时候会遇到在message获取存在不同程度的麻烦,onmessage只需调用一次,防止函数覆盖,可以统一在vuex中创建一个实例
整个过程类似ws.addEventLisener('message',func)
/*
* store.js
*
*/
let store = new Vuex.Store({
state:{
/*WS*/
WS: new Scocket(...config),/*这个看需求,有一些是放在登录后连接的*/
/*msg返回信息存放*/
WS_MSG: null,
}
})
<template></template>
<script>
/*
*
* 实际调用环境 test.vue,也可以直接放到App.vue中
*
*/
export default {
name:"test",
data(){return {}},
watch:{
/*添加watcher*/
'$store.WS_MSG':{
handler(newVal,oldVal){
//code...业务逻辑
},
/*下面两个属性可加可不加,加了稳一点*/
immidiate:true,
deep:true,
}
}
}
</script>
更多推荐
已为社区贡献3条内容
所有评论(0)