前端封裝WebSocket工具n

  1. Web API 提供的 WebSocket 類,封裝一個 Socket 類
// socket.js
import modal from '@/plugins/modal'
const baseURL = import.meta.env.VITE_APP_BASE_WS;
const EventTypes = ['open', 'close', 'message', 'error', 'reconnect'];
const DEFAULT_CHECK_TIME = 55 * 1000; // 心跳檢測的默認時間
const DEFAULT_CHECK_COUNT = 3; // 心跳檢測默認失敗重連次數
const DEFAULT_CHECK_DATA = { Type: 1, Parameters: ['alive'] }; // 心跳檢測的默認參數 - 跟后端協商的
const CLOSE_ABNORMAL = 1006; // WebSocket非正常關閉code碼class EventMap {deps = new Map();depend(eventType, callback) {this.deps.set(eventType, callback);}notify(eventType, event) {if (this.deps.has(eventType)) {this.deps.get(eventType)(event);}}
}class Socket extends WebSocket {heartCheckData = DEFAULT_CHECK_DATA;heartCheckTimeout = DEFAULT_CHECK_TIME;heartCheckInterval = null;heartCheckCount = DEFAULT_CHECK_COUNTconstructor(options, dep, reconnectCount = 0) {let _baseURL = baseURLconst { url, protocols, query = {}, greet = null, customBase = null } = options;const _queryParams = Object.keys(query).reduce((str, key) => {if (typeof query[key] !== 'object' && typeof query[key] !== 'function') {return str += str.length > 0 ? `&${key}=${query[key]}` : `${key}=${query[key]}`;} else {return str;}}, '');if (customBase) {_baseURL = customBase}super(`${_baseURL}${url}?${_queryParams}`, protocols);this._currentOptions = options;this._dep = dep;this._reconnectCount = reconnectCount;greet && Object.assign(this, {heartCheckData: greet})this.initSocket();}// 初始化WebSocketinitSocket() {// 監聽webSocket的事件this.onopen = function (e) {this._dep.notify('open', e);this.heartCheckStart();}this.onclose = function (e) {this._dep.notify('close', e);// 如果WebSocket是非正常關閉 則進行重連if (e.code === CLOSE_ABNORMAL) {if (this._reconnectCount < this.heartCheckCount) {this._reconnectCount++;const _socket = new Socket(this._currentOptions, this._dep, this._reconnectCount);this._dep.notify('reconnect', _socket);} else {return modal.msgError('WebSocket重連失敗, 請聯系技術客服!');}}}this.onerror = function (e) {this._dep.notify('error', e);}this.onmessage = function (e) {// 如果后端返回的是二進制數據if (e.data instanceof Blob) {const reader = new FileReader()reader.readAsArrayBuffer(e.data)reader.onload = (ev) => {if (ev.target.readyState === FileReader.DONE) {this._dep.notify('message', ev.target?.result);}}} else {// 處理普通數據try {const _parseData = JSON.parse(e.data);this._dep.notify('message', _parseData);} catch (error) {console.log(error)}}}}// 訂閱事件subscribe(eventType, callback) {if (typeof callback !== 'function') throw new Error('The second param is must be a function');if (!EventTypes.includes(eventType)) throw new Error('The first param is not supported');this._dep.depend(eventType, callback);}// 發送消息sendMessage(data, options = {}) {const { transformJSON = true } = options;let result = data;if (transformJSON) {result = JSON.stringify(data);}this.send(result);}// 關閉WebSocketcloseSocket(code, reason) {this.close(code, reason);}// 開始心跳檢測heartCheckStart() {this.heartCheckInterval = setInterval(() => {if (this.readyState === this.OPEN) {let transformJSON = typeof this.heartCheckData === 'object'this.sendMessage(this.heartCheckData, { transformJSON });} else {this.clearHeartCheck();}}, this.heartCheckTimeout)}// 清除心跳檢測clearHeartCheck() {clearInterval(this.heartCheckInterval);}// 重置心跳檢測resetHeartCheck() {clearInterval(this.heartCheckInterval);this.heartCheckStart();}
}
// 默認的配置項
const defaultOptions = {url: '',protocols: '',query: {},
}export const useSocket = (options = defaultOptions) => {if (!window.WebSocket) return modal.msgWarning('您的瀏覽器不支持WebSocket, 請更換瀏覽器!');const dep = new EventMap();const reconnectCount = 0;return new Socket(options, dep, reconnectCount);
}
  1. 使用這個封裝好的 useSocket 函數,以在 Vue3中使用為例
// xx.jsx or xx.vue
import { useSocket } from './socket.js'
const socket = ref(null) // WebSocket實例
const initWebSocket = () => {const options = {url: '/<your url>',query: {// something params},}socket.value = useSocket(options)socket.value.subscribe('open', () => {console.log('WebSocket連接成功!')const greet = 'hello'// 發送打招呼消息socket.value.sendMessage(greet)})socket.value.subscribe('close', reason => {console.log('WebSocket連接關閉!', reason)})socket.value.subscribe('message', result => {console.log('WebSocket接收到消息:', result)})socket.value.subscribe('error', err => {console.log('WebSocket捕獲錯誤:', err)})socket.value.subscribe('reconnect', _socket => {console.log('WebSocket斷開重連:', _socket)socket.value = _socket})
}
initWebSocket()
  1. debug 我們的心跳檢測是否有效
// 測試心跳檢測重連 手動模擬斷開的情況
if (this._reconnectCount > 0) return;
const tempTimer = setInterval(() => {this.close();if (this._reconnectCount < 3) {console.log('重連');this._reconnectCount++;const _socket = new Socket(this._currentOptions, this._dep, this._reconnectCount);this._dep.notify('reconnect', _socket);} else {return clearInterval(tempTimer);}
}, 3 * 1000)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/78841.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/78841.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/78841.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

TCP和UDP傳輸層協議

TCP&#xff08;Transmission Control Protocol&#xff09;和 UDP&#xff08;User Datagram Protocol&#xff09;是兩種常見的傳輸層協議&#xff0c;它們在網絡通信中發揮著不同的作用。二者在連接建立、可靠性、傳輸效率等方面存在顯著差異&#xff0c;適用于不同的應用場…

空域倫理與AI自主邊界的系統建構

在AI無人系統逐步參與城市空域治理的過程中&#xff0c;系統的“自主性”已不再僅是技術指標&#xff0c;而是直接影響合規性、安全性與社會接受度的倫理邊界議題。AI決策系統是否擁有“強干預能力”&#xff1f;行為觸發責任應歸屬何方&#xff1f;算法可否調優至“自我糾偏”…

在原生代碼(非webpack)里使用iview的注意事項

最近公司在做一個項目&#xff0c;使用的框架是iview,使用過程中同事遇到一些問題&#xff0c;這些問題對于有些同學來說根本就不是問題&#xff0c;但總會有同學需要&#xff0c;為了幫助不太會用的同學快速找到問題&#xff0c;做了如下整理&#xff1a; 下載vue,iview.min.j…

java代碼混淆

生成jar的時候混淆 目前最常用的Proguard,網上有很多介紹的文章&#xff0c;這種安全性較低 對已經生成的jar進行加密 加密庫:https://github.com/li571312729/classfinal 測試對jar進行加密 加密后如果正常調用的話會失敗 加密后jar反編譯查看不到代碼 使用密碼才能調用機…

【Linux】第十三章 訪問Linux文件系統

目錄 1. 存儲設備是什么&#xff1f;怎么理解分區和格式化&#xff1f; 2. 文件系統是什么&#xff1f; 3. 掛載是什么&#xff1f;掛載點是什么&#xff1f; 4. 怎么理解塊設備&#xff1f; 5. 在SATA附加存儲中&#xff0c;第一磁盤上的第一個分區和第二磁盤的第二個分區…

MCP 服務器搭建【stdio 類型】實現上市公司年報查詢總結,配合 Cherry Studio使用簡單

代碼解釋 這段 Python 代碼的主要功能是搭建一個基于 FastAPI 的 MCP 服務器,用于處理通過股票代碼查詢上市公司年報的請求,實現服務器向客戶端的實時消息推送。以下是對代碼各部分的詳細解釋: 完整代碼+使用 Cherry Studio 調用 MCP 服務器的方法,放在文章最后了 1. 導…

第六節:軟件安裝

理論知識 軟件安裝的方式&#xff1a;在 Linux 系統中&#xff0c;常見的軟件安裝方式有源碼安裝、在線安裝、deb 包安裝、RPM 包安裝、使用 Snap 管理軟件包等。不同的安裝方式適用于不同的軟件和場景。源碼安裝&#xff1a;源碼安裝是指從軟件的源代碼開始&#xff0c;進行編…

ubantu部署yolov5(第四集:模型加速)

參考鏈接&#xff1a; GitHub - ultralytics/yolov5: YOLOv5 &#x1f680; in PyTorch > ONNX > CoreML > TFLite TFLite,ONNX,CoreML,TensorRT Export -Ultralytics YOLO Docs 使用Neural Magic 的 DeepSparse 部署YOLOv5 -Ultralytics YOLO 文檔 sparseml/inte…

flutter 專題 五十六 Google 2020開發者大會Flutter專題

由于疫情的原因&#xff0c;今年的Google 開發者大會 (Google Developer Summit) 在線上舉行&#xff0c;本次大會以“代碼不止”為主題&#xff0c;全面介紹了產品更新以及一系列面向本地開發者的技術支持內容。我比較關注的是移動開發&#xff0c;在本次大會上&#xff0c;關…

開源模型應用落地-qwen模型小試-Qwen3-8B-快速體驗-pipeline方式(二)

一、前言 阿里云最新推出的 Qwen3-8B 大語言模型,作為國內首個集成“快思考”與“慢思考”能力的混合推理模型,憑借其 80 億參數規模及 128K 超長上下文支持,正在重塑 AI 應用邊界。該模型既可通過輕量化“快思考”實現低算力秒級響應,也能在復雜任務中激活深度推理模式,以…

「動態規劃::背包」01背包 / AcWing 2(C++)

概述 AcWing 2&#xff1a; 有 N 件物品和一個容量是 V 的背包。每件物品只能使用一次。 第 i 件物品的體積是 v[i]&#xff0c;價值是 w[i]。 求解將哪些物品裝入背包&#xff0c;可使這些物品的總體積不超過背包容量&#xff0c;且總價值最大。 輸出最大價值。 輸入格式 第一…

Java 中的 設計模式詳解

一&#xff1a;設計模式概述 &#xff08;1&#xff09;概述 &#xff08;2&#xff09;分類 創建型 行為型 結構型 二&#xff1a;軟件設計模式 2.1 開閉原則 &#xff08;1&#xff09;定義 在程序需要進行拓展的時候&#xff0c;不能修改原有代碼 使用到接口和抽象類&#x…

阿里qiankun微服務搭建

主服務 chat vue3 ts vite 子服務 ppt react 18 vite 子服務 agent 主服務 npm i vite-plugin-qiankun mian.ts import ./style/base.scss import virtual:svg-icons-register import { createApp } from vue import { createPinia } from piniaimport App from ./App.vue im…

安裝WSL2,配置Ubuntu圖像化界面

目錄 一、前言二、安裝WSL三、安裝圖像化界面四、參考 一、前言 Windows 子系統下的 Linux 子系統&#xff08;WSL&#xff0c;Windows Subsystem for Linux&#xff09;是微軟推出的一項功能&#xff0c;允許用戶在 Windows 系統中原生運行 Linux 環境&#xff0c;無需安裝虛…

圖像畸變-徑向切向畸變實時圖像RTSP推流

實驗環境 注意&#xff1a;ffmpeg進程stdin寫入兩張圖片的時間間隔不能太長&#xff0c;否則mediamtx會出現對應的推流session超時退出。 實驗效果 全部代碼 my_util.py #進度條 import os import sys import time import shutil import logging import time from datetime i…

Redis Sentinel 和 Redis Cluster 各自的原理、優缺點及適用場景是什么?

我們來詳細分析下 Redis Sentinel (哨兵) 和 Redis Cluster (集群) 這兩種方案的原理和使用場景。 Redis Sentinel (哨兵) 原理: Sentinel 本身是一個或一組獨立于 Redis 數據節點的進程。它的核心職責是監控一個 Redis 主從復制 (Master-Slave) 架構。多個 Sentinel 進程協同…

基于機器學習的電影票房預測

目錄 摘 要(完整下載鏈接附在文末) Abstract 1 緒 論 1.1 研究背景概述 1.2 國內外相關領域研究進展 1.3 電影票房預測技術概覽 1.3.1 利用人口統計學特征的方法 1.3.2 基于機器學習的預測模型 2 機器學習相關理論介紹與分析 2.1 機器學習算法理論 2.1.1卷積…

SVMSPro平臺獲取HTTP-FLV規則

SVMSPro平臺獲取HTTP-FLV規則 HTTP-FLV的服務端口為&#xff1a;53372&#xff0c;如需要公網訪問需要開啟這個端口 這里講的是如何獲取長效URL&#xff0c;短效&#xff08;時效性&#xff09;URL也支持&#xff0c;下回講 一、如何獲取HTTP-FLV實時流視頻 http://host:po…

ARM架構的微控制器總線矩陣

在 ARM 架構的微控制器&#xff08;MCU&#xff09;中&#xff0c;總線矩陣&#xff08;Bus Matrix&#xff09; 是總線系統的核心互連結構&#xff0c;負責協調多個主設備&#xff08;如 CPU、DMA、以太網控制器等&#xff09;對多個從設備&#xff08;如 Flash、SRAM、外設等…

AI賦能金融:智能投顧、風控與反欺詐的未來

AI賦能金融&#xff1a;智能投顧、風控與反欺詐的未來 系統化學習人工智能網站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目錄 AI賦能金融&#xff1a;智能投顧、風控與反欺詐的未來摘要引言一、智能投顧&#xff1a;從經驗驅動到人機協同…