【ES6】websocket封装类(增加重连事件和心跳事件)(适合在vue中使用)

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({****})之后保存在vuexstate中,全局方便调用而且可以保留状态

//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>
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值