狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

WEB頁面封裝WebSocket消息推送,干翻Ajax輪詢方式

admin
2024年7月2日 10:23 本文熱度 1261

使用AJAX和WebSocket都可以實(shí)現(xiàn)消息推送,但它們在實(shí)現(xiàn)方式和適用場景上有所不同。下面是使用這兩種技術(shù)實(shí)現(xiàn)消息推送的簡要說明。

AJax實(shí)現(xiàn)或WebSocket實(shí)現(xiàn)對(duì)比

AJAX 實(shí)現(xiàn)消息推送

AJAX(Asynchronous JavaScript and XML)允許你在不重新加載整個(gè)頁面的情況下,與服務(wù)器進(jìn)行數(shù)據(jù)交換。但是,傳統(tǒng)的AJAX并不直接支持實(shí)時(shí)消息推送,因?yàn)樗谡埱?響應(yīng)模式。為了模擬消息推送,你可以使用輪詢(polling)或長輪詢(long-polling)技術(shù)。

輪詢(Polling)

輪詢是定期向服務(wù)器發(fā)送請求,以檢查是否有新的消息。這種方法簡單但效率較低,因?yàn)榧词乖跊]有新消息的情況下,也會(huì)頻繁地發(fā)送請求。

function pollForMessages({
    $.ajax({
        url'/messages'// 假設(shè)這是獲取消息的API端點(diǎn)
        method'GET',
        successfunction(data{
            // 處理接收到的消息
            console.log(data);
            
            // 等待一段時(shí)間后再次輪詢
            setTimeout(pollForMessages, 5000); // 每5秒輪詢一次
        },
        errorfunction({
            // 處理請求失敗的情況
            setTimeout(pollForMessages, 10000); // 等待更長時(shí)間后重試
        }
    });
}

// 開始輪詢
pollForMessages();

長輪詢(Long-Polling)

長輪詢是輪詢的一種改進(jìn)方式。客戶端發(fā)起一個(gè)請求到服務(wù)器,服務(wù)器會(huì)保持這個(gè)連接打開直到有新消息到達(dá)或超時(shí),然后返回新消息或超時(shí)響應(yīng)。這種方式比簡單輪詢減少了無效的請求,但仍然存在一定的延遲和資源浪費(fèi)。

使用長輪詢時(shí),通常需要在服務(wù)器端有特殊的支持來保持連接直到有數(shù)據(jù)可以發(fā)送。

WebSocket 實(shí)現(xiàn)消息推送

WebSocket 提供了一個(gè)全雙工的通信通道,允許服務(wù)器主動(dòng)向客戶端推送消息。一旦建立了WebSocket連接,服務(wù)器和客戶端就可以隨時(shí)向?qū)Ψ桨l(fā)送消息,而不需要像AJAX那樣頻繁地發(fā)起請求。

WebSocket 客戶端實(shí)現(xiàn)

var socket = new WebSocket('ws://your-server-url');

socket.onopen = function(event{
    // 連接打開后,你可以向服務(wù)器發(fā)送消息
    socket.send('Hello Server!');
};

socket.onmessage = function(event{
    // 當(dāng)收到服務(wù)器發(fā)來的消息時(shí),觸發(fā)此事件
    console.log('Received:', event.data);
};

socket.onerror = function(error{
    // 處理錯(cuò)誤
    console.error('WebSocket Error:', error);
};

socket.onclose = function(event{
    // 連接關(guān)閉時(shí)觸發(fā)
    console.log('WebSocket is closed now.');
};

WebSocket 服務(wù)器端實(shí)現(xiàn)

服務(wù)器端實(shí)現(xiàn)WebSocket通常依賴于特定的服務(wù)器軟件或框架,如Node.js的ws庫、Java的Spring WebSocket等。這些庫或框架提供了處理WebSocket連接的API,你可以在這些連接上發(fā)送和接收消息。

在WebSocket服務(wù)器端,你可以保存與每個(gè)客戶端的連接,并在需要時(shí)向它們發(fā)送消息

下面開始做封裝WebSocket的介紹

想象

想象一下,你是一位超級(jí)快遞員,負(fù)責(zé)把客戶的包裹準(zhǔn)確無誤地送到指定的地址。這些包裹里裝的是WebSocket消息,而你的任務(wù)是根據(jù)每個(gè)包裹上的useridurl信息,找到正確的收件人并將包裹送達(dá)。

首先,你需要準(zhǔn)備一輛超級(jí)快遞車(也就是WebSocket連接)。這輛車非常智能,它可以記住多個(gè)收件人的地址(url),并且同時(shí)為他們運(yùn)送包裹。但是,每個(gè)收件人(userid)只能對(duì)應(yīng)一個(gè)地址,這樣才不會(huì)送錯(cuò)。

當(dāng)有客戶找你寄送包裹時(shí),他們會(huì)告訴你收件人的userid和地址url。你會(huì)把這些信息記在小本本上,然后告訴超級(jí)快遞車:“嘿,車車,我們要去這個(gè)地方送這個(gè)包裹給這個(gè)人!”

快遞車非常聽話,它會(huì)立即啟動(dòng)并前往指定的地址。一旦到達(dá),它就會(huì)靜靜地等待,直到有包裹需要送出。

當(dāng)你需要發(fā)送消息時(shí),就像把包裹放進(jìn)快遞車?yán)镆粯雍唵巍D阒恍韪嬖V快遞車:“給這個(gè)userid的人送這個(gè)包裹!”快遞車就會(huì)準(zhǔn)確無誤地將包裹送達(dá)給指定的收件人。

如果收件人回復(fù)了消息,快遞車就像個(gè)貼心小助手一樣,會(huì)第一時(shí)間把回信拿給你。你可以輕松地查看并處理這些回信。

這樣一來,你就不再需要親自跑腿送包裹了,超級(jí)快遞車會(huì)幫你搞定一切。你只需要告訴它去哪里、送給誰,然后坐等好消息就行啦!

  1. WebSocketMessenger(快遞服務(wù)公司) :

    • 負(fù)責(zé)建立和維護(hù)WebSocket連接。
    • 采用單例模式,確保同一時(shí)間只有一個(gè)實(shí)例在運(yùn)行。
    • 存儲(chǔ)收件人(recipient)和地址(address)信息。
    • 提供發(fā)送消息(send_message)的方法。
  2. 快遞員(WebSocket連接實(shí)例) :

    • WebSocketMessenger創(chuàng)建和管理。
    • 負(fù)責(zé)實(shí)際的消息傳遞工作。
    • 知道如何與指定的收件人通信(通過地址)。
  3. 客戶(發(fā)送消息的人) :

    • 使用WebSocketMessenger的服務(wù)來發(fā)送消息。
    • 提供收件人信息和消息內(nèi)容。
  4. 收件人(接收消息的人) :

    • 在WebSocket連接的另一端,接收來自WebSocketMessenger傳遞的消息。

這些角色通過WebSocket連接進(jìn)行交互,實(shí)現(xiàn)了消息的發(fā)送和接收。WebSocketMessenger作為服務(wù)提供者,管理著快遞員(WebSocket連接實(shí)例),而客戶和收件人則是服務(wù)的使用者。

代碼層面

服務(wù)node代碼可以看上篇文章: 僅僅只會(huì)Ajax,那就out了!WebSocket實(shí)戰(zhàn)解鎖實(shí)時(shí)通信新境界![1]

// WebSocketMessenger(快遞服務(wù)公司)
class WebSocketManager {
  constructor(url = null, userId = null, receiveMessageCallback = null) {
    this.socket = null // WebSocket 對(duì)象
    this.sendTimeObj = null // 發(fā)送信息給服務(wù)端的重復(fù)調(diào)用的時(shí)間定時(shí)器
    this.reconnectTimeObj = null // 嘗試鏈接的宏觀定時(shí)器
    this.reconnectTimeDistance = 5000 // 重連間隔,單位:毫秒
    this.maxReconnectAttempts = 10 // 最大重連嘗試次數(shù)
    this.reconnectAttempts = 0 // 當(dāng)前重連嘗試次數(shù)
    this.id = userId //用戶ID(業(yè)務(wù)邏輯,根據(jù)自己業(yè)務(wù)需求調(diào)整)
    this.url = url // WebSocket 連接地址
    this.receiveMessageCallback = receiveMessageCallback // 接收消息回調(diào)函數(shù)
  }

  /**
   * 開啟WebSocket
   */

  async start() {
    if (this.url && this.id) {
      // 連接WebSocket
      this.connectWebSocket()
    } else {
      console.error('WebSocket erros: 請傳入連接地址和用戶id')
    }
  }

  /**
   * 創(chuàng)建WebSocket連接, 超級(jí)快遞車
   */

  connectWebSocket() {
    // 通過id生成唯一值(服務(wù)端要求,具體根據(jù)自己業(yè)務(wù)去調(diào)整)
    let id = `${this.id}-${Math.random()}`
    // 創(chuàng)建 WebSocket 對(duì)象
    this.socket = new WebSocket(this.url, id) // 快遞員(WebSocket連接實(shí)例

    // 處理連接打開事件
    this.socket.onopen = (event) => {
      // 給服務(wù)端發(fā)送第一條反饋信息
      this.startSendServe()
    }

    // 處理接收到消息事件
    this.socket.onmessage = (event) => {
      this.receiveMessage(event)
    }

    // 處理連接關(guān)閉事件
    this.socket.onclose = (event) => {
      // 清除定時(shí)器
      clearTimeout(this.sendTimeObj)
      clearTimeout(this.reconnectTimeObj)
      // 嘗試重連
      if (this.reconnectAttempts < this.maxReconnectAttempts) {
        this.reconnectAttempts++
        console.log('重試鏈接次數(shù):'this.reconnectAttempts)
        this.reconnectTimeObj = setTimeout(() => {
          this.connectWebSocket()
        }, this.reconnectTimeDistance)
      } else {
        // 重置重連次數(shù)
        this.reconnectAttempts = 0
        console.error(
          'WebSocketManager erros: Max reconnect attempts reached. Unable to reconnect.'
        )
      }
    }

    // 處理 WebSocket 錯(cuò)誤事件
    this.socket.onerror = (event) => {
      console.error('WebSocketManager error:', event)
    }
  }

  /**
   * 發(fā)送給node的第一條信息
   */

  startSendServe() {

    this.sendMessage('hi I come from client')
  }

  /**
   * 發(fā)送消息
   * @param {String} message 消息內(nèi)容
   */

  sendMessage(message) {
    if (this.socket.readyState === WebSocket.OPEN) {
      this.socket.send(message)
    } else {
      console.error(
        'WebSocketManager error: WebSocket connection is not open. Unable to send message.'
      )
    }
  }

  /**
   * 接收到消息
   */

  receiveMessage(event) {
    // 根據(jù)業(yè)務(wù)自行處理
    console.log('receiveMessage:', event.data)
    this.receiveMessageCallback && this.receiveMessageCallback(event.data)
  }

  /**
   * 關(guān)閉連接
   */

  closeWebSocket() {
    this.socket.close()
    // 清除定時(shí)器 重置重連次數(shù)
    clearTimeout(this.sendTimeObj)
    clearTimeout(this.reconnectTimeObj)
    this.reconnectAttempts = 0
  }
}

代碼解讀

該類用于管理和控制WebSocket連接,包括連接建立、消息接收、重連機(jī)制等。下面是對(duì)代碼的詳細(xì)解讀:

構(gòu)造函數(shù) constructor

  • url: WebSocket的連接地址。
  • userId: 用戶的ID,用于業(yè)務(wù)邏輯處理。
  • receiveMessageCallback: 接收消息時(shí)的回調(diào)函數(shù)。
  • 初始化了一些成員變量,包括socket(WebSocket對(duì)象)、定時(shí)器對(duì)象(sendTimeObjreconnectTimeObj)、重連間隔和嘗試次數(shù)等。

start 方法

  • 檢查urluserId是否存在,若存在則調(diào)用connectWebSocket方法建立WebSocket連接。

connectWebSocket 方法

  • 生成一個(gè)基于用戶ID和隨機(jī)數(shù)的唯一值作為WebSocket的子協(xié)議(或協(xié)議片段)。
  • 創(chuàng)建新的WebSocket連接。
  • 設(shè)置了WebSocket的onopenonmessageoncloseonerror事件處理器。

事件處理器

  • onopen: 當(dāng)WebSocket連接打開時(shí)觸發(fā),開始發(fā)送消息給服務(wù)端(通過startSendServe方法,該方法在代碼片段中未給出)。
  • onmessage: 當(dāng)接收到服務(wù)端發(fā)送的消息時(shí)觸發(fā),調(diào)用receiveMessage方法處理消息。
  • onclose: 當(dāng)WebSocket連接關(guān)閉時(shí)觸發(fā),首先清除相關(guān)定時(shí)器,然后嘗試重連。如果重連次數(shù)未達(dá)到最大限制,則設(shè)置定時(shí)器在一段時(shí)間后重新調(diào)用connectWebSocket進(jìn)行重連;如果達(dá)到最大重連次數(shù),則重置重連次數(shù)并輸出錯(cuò)誤信息。
  • onerror: 當(dāng)WebSocket發(fā)生錯(cuò)誤時(shí)觸發(fā),輸出錯(cuò)誤信息。 當(dāng)服務(wù)端斷開后開始重連

image.png
image.png

receiveMessage 方法

  • 該方法應(yīng)該是用來處理從服務(wù)端接收到的消息,具體實(shí)現(xiàn)取決于業(yè)務(wù)邏輯。根據(jù)傳入的回調(diào)函數(shù)receiveMessageCallback,可以對(duì)接收到的消息進(jìn)行相應(yīng)處理

使用Demo

index.html

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./webSocketManager.js"></script>
    <script>
        // const WebSocketManager = require('./webSocketManager.js')
        console.log(WebSocketManager)
        /**
         * 接收消息回調(diào)
         */

        const receiveMessage = (res)=>{
            console.log('接收消息回調(diào):',res)
        }
        const socketManager = new WebSocketManager('ws://localhost:3000''userid292992', receiveMessage)
        socketManager.start()

    
</script>
</head>

導(dǎo)入模塊即可使用

總結(jié):

相對(duì)完善的WebSocket管理器,能夠處理連接建立、消息接收和重連等常見場景。但需要注意的是,具體的業(yè)務(wù)邏輯和錯(cuò)誤處理可能需要根據(jù)實(shí)際情況進(jìn)行進(jìn)一步的完善和優(yōu)化。


該文章在 2024/7/2 10:23:34 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲(chǔ)管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved