Dva 中使用 WebSocket

一、概述

Websocket 是 H5 自帶的一個 API,隨著越來越多的瀏覽器都自適應(yīng)了 H5 的特性,許多瀏覽器也內(nèi)置了 WebSocket API。也就是說 WebSocket 和 window、document 一樣作為全局變量可以直接使用。

要在瀏覽器端使用 WebSocket,首先需要服務(wù)端支持 WebSocket,假設(shè)現(xiàn)在服務(wù)端已提供 WebSocket 服務(wù),訪問地址:ws://localhost:8080,簡單介紹下瀏覽器使用方法。

// 連接 Websocket 服務(wù)端
const ws = new WebSocket("ws://localhost:8080");

// 監(jiān)聽連接上 Websocket 服務(wù)端觸發(fā)事件
ws.onopen = function (e) {
  console.log('連接上 ws 服務(wù)端了');
  // ws.send() 給服務(wù)端發(fā)送數(shù)據(jù)
  ws.send('我是客戶端,我接收到你的請求了');
}

// 監(jiān)聽 Websocket 服務(wù)端傳來消息觸發(fā)事件
ws.onmessage = function(msg) { 
    // msg.data 接收服務(wù)端傳遞過來的數(shù)據(jù)
    console.log('接收服務(wù)端發(fā)過來的消息: %o', msg.data); 
}; 

// 監(jiān)聽 Websocket 服務(wù)端連接斷開觸發(fā)事件
ws.onclose = function (e) {
    console.log('ws 連接關(guān)閉了');
}       

注意事項(xiàng): WebSocket 通信傳遞的數(shù)據(jù)是字符串,即便瀏覽器端傳給服務(wù)端的是個對象,在服務(wù)端接收時也會變成字符串,可以通過 JSON.parse(msg.data) 解析成對象。

二、dva 中使用 WebSocket

下面是我寫小說爬蟲用到的部分代碼,點(diǎn)擊爬取,在瀏覽器端打印服務(wù)端爬蟲日志。

瀏覽器端實(shí)時打印服務(wù)端日志

dva 是基于 React 的狀態(tài)管理器,不能直接對 Dom 進(jìn)行操作。要持續(xù)不斷的接收服務(wù)端響應(yīng)數(shù)據(jù),需要在構(gòu)造器中定義一個 state 屬性進(jìn)行接收。直接在 routes 目錄下的頁面中連接服務(wù)端 WebSocket 并調(diào)用 API 接口。

(用箭頭函數(shù)寫組件的寫法是沒有 state 特性的,這一點(diǎn)在 React 官方文檔中有詳細(xì)說明,具體可參考 React 開發(fā)中不得不注意的兩個大坑

// src/routes/novel/index.js
class NovelComp {
  constructor (props) {
    super(props);
    this.state = { result: '' };   // 接收 Websocket 響應(yīng)數(shù)據(jù)
  }

  handleSteal (flag) {
    const ws = new WebSocket('ws://localhost:8080');
    let result = this.state.result;

    ws.onopen = function (e) {
      console.log('連接上 ws 服務(wù)端了');
      ws.send(JSON.stringify({ flag: flag, data: currentItem }));
    }
    ws.onmessage = function(msg) { 
        console.log('接收服務(wù)端發(fā)過來的消息: %o', msg); 
        result += msg.data + '\n'; 
        that.setState({ result: result });
    }; 
    ws.onclose = function (e) {
        console.log('ws 連接關(guān)閉了');
    }
  }

  render () {
      return (
        <Modal>
          <Button></Button>
          ....  
        <Modal/>
      );
  }
}

三、一直連接 WebSocket

上面的 WebSocket 應(yīng)用場景是點(diǎn)擊按鈕才會連接 WebSocket,關(guān)閉模態(tài)框 WebSocket 連接即斷開。

有些需求需要 WebSocket 一直連接,比如 待辦事項(xiàng)主動提醒。如果其它操作新增了一條通知,當(dāng)前用戶的通知條目應(yīng)當(dāng)自動變成 6,而不是下一次刷新完再更新。

待辦事項(xiàng)主動提醒

由于 dva 本身的特性,如果刷新頁面,dva 所有狀態(tài)容器中的值都會清空,與此同時 WebSocket 連接也會斷開,也就沒法監(jiān)聽服務(wù)端傳過來的數(shù)據(jù)。

解決方案: 修改 src/models/novel.js 的 subscriptions 屬性。

subscriptions: {
    setupHistory ({ dispatch, history }) {
      history.listen((location) => {
        if (location.pathname.indexOf('reptile/novel')) {
           const ws = new WebSocket('ws://localhost:8080');
           dispatch({
              type: 'updateState', 
              payload: { ws: ws },
           });
        }
      })
    },
  },

subscriptions 下面 setupHistory 的作用是監(jiān)聽瀏覽器地址欄地址如果變成當(dāng)前頁面 reptile/novel 就創(chuàng)建 WebSocket 連接,這樣就能保證每次進(jìn)入這個頁面的時候都已連接 WebSocket。

對于 待辦事項(xiàng)主動提醒 那個需求,只需在布局文件中的 subscriptions 中添加上述代碼即可。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,940評論 1 92
  • 學(xué)習(xí)本質(zhì)上是一個認(rèn)知過程,當(dāng)我們在學(xué)習(xí)時,這個認(rèn)知過程到底是怎樣發(fā)生的呢?本文以多媒體學(xué)習(xí)的認(rèn)知過程為例,說明「意...
    英知學(xué)習(xí)閱讀 1,982評論 0 2
  • 人真的是一種適應(yīng)力很強(qiáng)的生物。無論你呼朋引伴萬眾矚目,還是郁郁寡歡對月獨(dú)酌,你都會漸漸習(xí)慣,漸漸覺得并沒有什么特殊...
    恒變閱讀 603評論 0 3
  • 我是日記星球第345號星寶寶,正在參加日記星球第十六期21天蛻變之旅,這是我的第八十篇原創(chuàng)日記。 人們常說可憐天下...
    重塑牛仔閱讀 295評論 0 1
  • 今天是莎倫的生日,22歲生日。 沒有什么特別的事情發(fā)生,天氣沒什么特別的,陽臺角落里的盆栽沒什么特別的。不同于昨天...
    莎倫小姐閱讀 206評論 0 0

友情鏈接更多精彩內(nèi)容