前端websocket获取数据后需要存本地吗_websocket基础

实时推送技术

  • 实时推送技术的实现大体有两种方式,Ajax轮询WebSocket
    • Ajax轮询 是通过设定特定的时间间隔(如:1s), 定时向服务器发送HTTP请求,从而获取数据,达到实时推送的效果。这种传统的形式有明显的缺点,就是客户端需要不断地向服务端发送请求,增加服务器压力
    • WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯

138b18a4a00cb666dbd1db1f9abe5a0c.png

ws握手与数据传输 图片来源:菜鸟教程

简单介绍

HTML5 标准

  • HTML5 新增的协议

单个 TCP 连接

  • 在单个 TCP 连接上进行全双工(能够同一时候发送和接收)通讯的协议

基于HTTP进行链接

  • Webscoket 并不是全新的协议,而是利用了 HTTP 协议来建立连接(完成握手)
  • 一次握手,永久连接,双向数据传输
  • 通过查看浏览器的request这是一个以HTTP协议为基础的get请求,握手只会进行一次,随后便可以进行双向数据传递

不存在跨域的问题

  • webscoket 协议本身不要求同源策略,不存在跨域的问题,本身就跨域。
  • 但是,浏览器会发送 Origin 的 HTTP头 给服务器,服务器可以根据 Origin 拒绝这个 WebSocket 请求。所以,是否要求同源要看服务器端如何检查。

统一资源标识符

  • wswss
  • 按照HTML5标准是有对应关系的 HTTP -> ws; HTTPS -> wss

心跳检测

  • 链接时间长无数据来往会自动断线,浏览器不会为你维持连接,需要增加心跳检测来保持通道畅通

断线重连

  • 由于网络原因或服务器不稳定造成的 webscoket 断线,需要进行重连

属性(已创建webscoket实例的情况下)

  • Socket.readyState: 只读属性 readyState 表示连接状态
    • 0 - 表示连接尚未建立。
    • 1 - 表示连接已建立,可以进行通信。
    • 2 - 表示连接正在进行关闭。
    • 3 - 表示连接已经关闭或者连接不能打开。
  • Socket.bufferedAmount: 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

方法(已创建webscoket实例的情况下)

  • Socket.onopen: 连接建立时触发
  • Scoket.onmessage: 客户端接收服务端数据时触发
  • Scoket.onerror: 通信发生错误时触发
  • Scoket.onclose: 连接关闭时触发

握手阶段

  • 一个握手请求
GET /chat HTTP/1.1
Host: server.xxx.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: xxxx
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://xxx.com
  • 相比正常的 HTTP request ,多了两个参数 Upgrade: websocketConnection: Upgrade ,这两个参数是告诉服务器,我发起的是webscoket请求。

使用 Webscoket

创建实例

  • var Socket = new WebSocket(url, [protocol]);
    • 第一个参数 url, 指定连接的 URL
    • 第二个参数 protocol 是可选的,指定了可接受的子协议

发送消息

  • 链接成功后向服务器 send 消息 (JSON格式)
Socket.onopen = function(){
  // Web Socket 已连接上,使用 send() 方法发送数据
  let params = {
  		data: '测试发送数据'
	}
  Socket.send(JSON.stringify(params))
  alert("数据发送中...")
}

接收消息

  • 使用 webscoket 自带方法接收服务器推送消息 (JSON格式)
Socket.onmessage = function (e) { 
  let res = JSON.parse(e.data)
  alert("数据已接收...")
}

关闭连接

  • 发生 error 或者主动关闭连接
Scoket.onerror = function(){
	// 发生错误
}
Socket.onclose = function(){ 
  // 关闭 websocket
  alert("连接已关闭...")
}

一个 webscoket 实例

本实例基于一个 Vue-cli 项目

创建思路

工厂函数抽离

  • 将 webscoket 进行封装,以进行实例化

同Vue实例下需要创建多个 webscoket

  • 利用 ES6 class 创建
  • path 可自定义传入

webscoket 回调单独处理

  • webscoket handler 通过创建实例后挂载
  • 挂载函数自定义

心跳检测

  • 实例添加公用心跳检测

Ready State 抽离

  • 实例封装 readystate 状态,便于获取

断线重连

  • 断线重连单独在使用示例时进行处理

代码部分

webSocket部分

// scoket.js
const webscketurl = process.env.BACKEND_URL // 利用node环境变量设置scoket path

class WebSocketUtil{
  constructor(wspath){
    let protocol = (window.location.protocol == 'https:') ? 'wss://' : 'ws://';
    // 判断当前使用协议头(上一篇webscoket基础已讲过)
    let wsuri = protocol + webscketurl + wspath
    
    this.websock = new WebSocket(wsuri)
    // new 实例
  }
  
  // 心跳检测
  heartCheck(){ 
    let self = this;
    if (this.timeoutObj) {
      clearInterval(this.timeoutObj)
    }
    this.timeoutObj = setInterval(function(){
      // 这里发送一个心跳,后端收到后,返回一个心跳消息,
      // onmessage拿到返回的心跳就说明连接正常
      if (self.readyState() != 1) {
        clearInterval(self.timeoutObj)
      }
      self.websock.send("HeartBeat");
      // 发送心跳检测
      console.log("HeartBeat");
    }, 10000)
  }
  
  // 实例创建后自定义创建 handler
  on(funName,handler){
      this.websock[`on${funName}`] = handler
    // 封装onmessage、onclose、onopen、onerror方法
  }
 
  // 发送scoket数据
  send(msg){
    this.websock.send(msg)
  }
  
  // 监听websock链接状态
  readyState(){
  // 获取webscoket实例链接状态 0:正在建立连接连接,还没有完成 1:连接成功,可以进行通信 2:连接正在进行关闭握手,即将关闭 3:连接已经关闭或者根本没有建立
    return this.websock.readyState;
  }
}

// 导出实例
export default WebSocketUtil

实例创建部分

// index.vue
import $WebSocketUtil from '../../api/scoket.js'

// 实例化聊天scoket
initScoket() {
	let token = this.$cookies.get('token')
	let pathData = '/chat?token=' + token
	this.webscoketChat = new $WebSocketUtil(pathData)
	this.webscoketChat.on('message', this.websocketonmessage)
	this.webscoketChat.on('open', this.websocketonpen)
	this.webscoketChat.on('error', this.websocketonerror)
	this.webscoketChat.on('close', this.websocketonerror)
	Vue.prototype.$scoketChat = this.webscoketChat
},

// socket建立成功后开始进行心跳检测
websocketonpen() {
	this.webscoketChat.heartCheck()
},

// 发生错误断线重连
websocketonerror() {
	let self = this
	if (this.reconnectChat) { return }
	this.reconnectChat = true
	setTimeout(function () {
	  self.initScoket()
	  console.log("Chat正在重连...")
	  self.reconnectChat = false
	}, 10000)
},

// 接收 webscoket 消息
websocketonmessage(e) {
	let res = JSON.parse(e.data);
	HandleChat(res.type,res.data,res.wxId || '');
},

作者:轻易科技研发中心 前端部-张晓斌

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值