【前端】websocket 讲解与项目中的使用(附源码)

您所在的位置:网站首页 websocket应用重置 【前端】websocket 讲解与项目中的使用(附源码)

【前端】websocket 讲解与项目中的使用(附源码)

2024-07-16 21:01| 来源: 网络整理| 查看: 265

websocket 实战(附源码) 写在前面创建连接监听事件属性&方法属性方法 心跳要点总结问题思考扩展知识源代码

写在前面

本文不会去分析 websocket 与 http 接口的区别,也不会写太多基础知识的介绍。只介绍 websocket 在前端开发中的实际应用(附源码)

websocket 作为全双工通信工具,在 web 开发中,用于前后端之间的消息推送、实时通信;这一点是 http 接口无法代替的(因为 websocket 是更优雅,性能更好的方式)

其实 websocket 是简单的。但是,很多人在第一次使用它的时候,会有很多疑问以及无从下手的问题。

下面开始 websocket 在项目中的使用。

创建连接 var ws = new WebSocket(url, [protocol])

第一个参数 url,指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。

例如:

let url = `${process.env['VUE_APP_WEBSOCKET']}/websocket` let ws = new WebSocket(url)

即可拿到一个 ws 实例。

监听事件 ws.addEventListener('open', e => { console.log('长连接连接成功') // 连接成功后的回调函数,连接成功后一般需要开启心跳方法 clearTimeout(timer.reconnectObj) dispatch('wsHeartStart') }) ws.addEventListener('message', e => { // 接收服务端数据时触发的回调函数 dispatch('wsHearReset') dispatch('handlerWSMessage', e) }) ws.addEventListener('close', e => { // 连接关闭时触发 dispatch('handlerWSClose', e) }) ws.addEventListener('error', e => { // 通信发生错误时触发 dispatch('handlerWSError', e) }) 属性&方法

Websocket 有哪些属性和方法呢?

属性 wx.readyState

readyState 表示连接状态,=> 状态常量介绍

wx.bufferedAmount

更多属性介绍,点击移步到官方文档

方法 ws.send(data) // 发送数据ws.close([code[, reason]]) // 关闭连接 心跳

心跳 是 websocket 中的一个概念,就是在 websocket 中用定时器,定时向服务器发送一个消息内容,我们约定,如果后端收到这个消息内容,就要向前端回一个消息内容。如果前端没有收到消息回复,则有可能 websocket 断掉了,那么就要进行重连操作,来保证我们的 websocket 处于连接状态。

let url = `${process.env['VUE_APP_WEBSOCKET']}/websocket` let ws = new WebSocket(url) ws.addEventListener('open', e => { console.log('长连接连接成功') // 执行心跳方法 dispatch('wsHeartStart') })

websocket 链接成功以后,开启心跳方法。心跳功能的实现如下:

const state = { ws: null, // 心跳时间(s) wsTimeout: 20, // 等待心跳响应时间(s),等待心跳的响应时间要大于心跳时间5s以上 waitHeartTime: 25 } // 开启心跳 wsHeartStart({ state, dispatch }) { timer.wsTimeoutObj = setTimeout(() => { if(state.ws && state.ws.readyState == 1) { state.ws.send('') } else { dispatch('handlerWSError') } }, state.wsTimeout * 1000) timer.serverTimeoutObj = setTimeout(() => { console.log('接收心跳异常!') dispatch('handlerWSError') }, state.waitHeartTime * 1000) }

稍微解释一下:上面这个代码片段,描述了心跳的基本意思;就是用定时器去向服务端发送一个空的字符串,我们与后端约定,当后端 ws 收到空字符串的时候,要回一个字符串。如果我们没有收到,则判断为 接收心跳异常,准备重连机制。(完整代码在文章末尾)

要点总结

要点总结的内容,建议大家细细品一下。

WebSocket 协议本质上是一个基于 TCP 的协议。为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息 "Upgrade: WebSocket" 表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。【如下图:】

在这里插入图片描述

软件通信有七层结构,下三层结构偏向与数据通信,上三层更偏向于数据处理,中间的传输层则是连接上三层与下三层之间的桥梁,每一层都做不同的工作,上层协议依赖于下层协议。基于这个通信结构的概念。Socket 其实并不是一个协议,是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口。当两台主机通信时,让 Socket 去组织数据,以符合指定的协议。TCP 连接则更依靠于底层的 IP 协议,IP 协议的连接则依赖于链路层等更低层次。WebSocket 则是一个典型的应用层协议。总的来说:Socket 是传输控制层协议,WebSocket 是应用层协议。 问题思考 如何做鉴权操作,例如 ws 请求中添加自定义 headers ? 扩展知识

那么,除了 websocket 还有哪些能实现长连接的工具呢?

1、SSE(Server-sent Events) SSE(Server-sent Events)是 WebSocket 的一种轻量代替方案,使用 HTTP 协议。 => Server-Sent Events 教程

2、stomp 介绍

3、MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议) MQTT JavaScript 客户端库 MQTT 入门介绍

4、课外阅读:WebSocket 是什么原理?为什么可以实现持久连接?

源代码 import { EventLsbridge } from '@/common/eventLsbridge' import { loadFromSession } from '@/common/session-storage' import { Message } from 'element-ui' const timer = { reconnectObj: null, wsTimeoutObj: null, serverTimeoutObj: null, // 重连时间间隔(s) reconnectTime: 3 } const state = { ws: null, // 心跳时间(s) wsTimeout: 20, // 等待心跳响应时间(s),等待心跳的响应时间要大于心跳时间4s以上 waitHeartTime: 24 } const mutations = { set_reconnectObj: (state, val) => { state.reconnectObj = val }, } const actions = { // 心跳重置 wsHearReset({ dispatch }) { clearTimeout(timer.serverTimeoutObj) clearTimeout(timer.wsTimeoutObj) dispatch('wsHeartStart') }, // 开启心跳 wsHeartStart({ state, dispatch }) { timer.wsTimeoutObj = setTimeout(() => { if(state.ws && state.ws.readyState == 1) { state.ws.send('') } else { dispatch('handlerWSError') } }, state.wsTimeout * 1000) timer.serverTimeoutObj = setTimeout(() => { console.log('接收心跳异常!') dispatch('handlerWSError') }, state.waitHeartTime * 1000) }, // 初始化ws连接 initWebsocket({ dispatch, state }) { if (state.ws) { return } else { return new Promise(resolve => { let url = `${process.env['VUE_APP_WEBSOCKET']}/websocket` state.ws = new WebSocket(url) state.ws.addEventListener('open', e => { console.log('长连接连接成功') clearTimeout(timer.reconnectObj) dispatch('wsHeartStart') }) state.ws.addEventListener('message', e => { dispatch('wsHearReset') dispatch('handlerWSMessage', e) }) state.ws.addEventListener('close', e => { console.log('ws close') dispatch('handlerWSClose', e) }) state.ws.addEventListener('error', e => { console.log('ws error') dispatch('handlerWSError', e) }) }) } }, handlerSend({state}, id = -1) { if(!state.ws) { return } if(state.ws.readyState == 1) { state.ws.send( JSON.stringify({ id }) ) } }, handlerWSClose({ state }, e) { state.ws?.close() }, handlerWSError({state, dispatch}, e) { console.log('ws-error') state.ws?.close() state.ws = null dispatch('reconnect') }, reconnect({state, commit, dispatch}) { console.log('ws-重连') clearTimeout(timer.wsTimeoutObj) clearTimeout(timer.serverTimeoutObj) clearTimeout(timer.reconnectObj) if (loadFromSession('userInfo')?.userId) { Message.warning('网络出现异常,请检查网络后尝试刷新页面') } timer.reconnectObj = window.setTimeout(() => { dispatch('initWebsocket') timer.reconnectTime += 4 if(timer.reconnectTime > 60) { timer.reconnectTime = 20 } }, timer.reconnectTime * 1000) }, // ws回调 handlerWSMessage({state}, e) { let respData = {} try { respData = JSON.parse(e.data) } catch (e) { // not todo } if (respData?.data) { EventLsbridge.vueEmit(EventLsbridge.eventName.wsData, respData) } } } export default { namespaced: true, state, mutations, actions }

-----------------(正文完)------------------

前端学习交流群,想进来面基的,可以加群: 685486827,832485817; Vue学习交流 React学习交流

写在最后: 约定优于配置 —— 软件开发的简约原则

--------------------------------(完)--------------------------------------

我的: 个人网站: https://neveryu.github.io/neveryu/ Github: https://github.com/Neveryu 新浪微博: https://weibo.com/Neveryu 微信: miracle421354532

更多学习资源请关注我的新浪微博…好吗



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3