<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 12848字,需瀏覽 26分鐘

           ·

          2024-07-18 08:20

             

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

          AJax實現(xiàn)或WebSocket實現(xiàn)對比

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

          AJAX(Asynchronous JavaScript and XML)允許你在不重新加載整個頁面的情況下,與服務器進行數(shù)據(jù)交換。但是,傳統(tǒng)的AJAX并不直接支持實時消息推送,因為它基于請求-響應模式。為了模擬消息推送,你可以使用輪詢(polling)或長輪詢(long-polling)技術(shù)。

          輪詢(Polling)

          輪詢是定期向服務器發(fā)送請求,以檢查是否有新的消息。這種方法簡單但效率較低,因為即使在沒有新消息的情況下,也會頻繁地發(fā)送請求。

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

          // 開始輪詢
          pollForMessages();

          長輪詢(Long-Polling)

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

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

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

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

          WebSocket 客戶端實現(xiàn)

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

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

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

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

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

          WebSocket 服務器端實現(xiàn)

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

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

          下面開始做封裝WebSocket的介紹

          想象

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

          首先,你需要準備一輛超級快遞車(也就是WebSocket連接)。這輛車非常智能,它可以記住多個收件人的地址(url),并且同時為他們運送包裹。但是,每個收件人(userid)只能對應一個地址,這樣才不會送錯。

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

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

          當你需要發(fā)送消息時,就像把包裹放進快遞車里一樣簡單。你只需告訴快遞車:“給這個userid的人送這個包裹!”快遞車就會準確無誤地將包裹送達給指定的收件人。

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

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

          1. WebSocketMessenger(快遞服務公司)

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

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

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

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

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

          代碼層面

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

          // WebSocketMessenger(快遞服務公司)
          class WebSocketManager {
            constructor(url = null, userId = null, receiveMessageCallback = null) {
              this.socket = null // WebSocket 對象
              this.sendTimeObj = null // 發(fā)送信息給服務端的重復調(diào)用的時間定時器
              this.reconnectTimeObj = null // 嘗試鏈接的宏觀定時器
              this.reconnectTimeDistance = 5000 // 重連間隔,單位:毫秒
              this.maxReconnectAttempts = 10 // 最大重連嘗試次數(shù)
              this.reconnectAttempts = 0 // 當前重連嘗試次數(shù)
              this.id = userId //用戶ID(業(yè)務邏輯,根據(jù)自己業(yè)務需求調(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連接, 超級快遞車
             */

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

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

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

              // 處理連接關(guān)閉事件
              this.socket.onclose = (event) => {
                // 清除定時器
                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 錯誤事件
              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è)務自行處理
              console.log('receiveMessage:', event.data)
              this.receiveMessageCallback && this.receiveMessageCallback(event.data)
            }

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

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

          代碼解讀

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

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

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

          start 方法

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

          connectWebSocket 方法

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

          事件處理器

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

          receiveMessage 方法

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

          使用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>

          導入模塊即可使用

          總結(jié):

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

          瀏覽 135
          1點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          1點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲一区二区电影网站 | 极品人妻超碰在线 | 一级无码视 | 艹比网| www.久久久久久 |