Dva 中使用 WebSocket

1、概述

Websocket 是 H5 自帶的一個 API,隨着愈來愈多的瀏覽器都自適應了 H5 的特性,許多瀏覽器也內置了 WebSocket API。也就是說 WebSocket 和 window、document 同樣做爲全局變量能夠直接使用。瀏覽器

要在瀏覽器端使用 WebSocket,首先須要服務端支持 WebSocket,假設如今服務端已提供 WebSocket 服務,訪問地址:ws://localhost:8080,簡單介紹下瀏覽器使用方法。socket

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

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

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

// 監聽 Websocket 服務端鏈接斷開觸發事件
ws.onclose = function (e) {
    console.log('ws 鏈接關閉了');
}

注意事項: WebSocket 通訊傳遞的數據是字符串,即使瀏覽器端傳給服務端的是個對象,在服務端接收時也會變成字符串,能夠經過 JSON.parse(msg.data) 解析成對象。函數

2、dva 中使用 WebSocket

下面是我寫小說爬蟲用到的部分代碼,點擊爬取,在瀏覽器端打印服務端爬蟲日誌。佈局

瀏覽器端實時打印服務端日誌

dva 是基於 React 的狀態管理器,不能直接對 Dom 進行操做。要持續不斷的接收服務端響應數據,須要在構造器中定義一個 state 屬性進行接收。直接在 routes 目錄下的頁面中鏈接服務端 WebSocket 並調用 API 接口。this

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

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

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

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

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

3、一直鏈接 WebSocket

上面的 WebSocket 應用場景是點擊按鈕纔會鏈接 WebSocket,關閉模態框 WebSocket 鏈接即斷開。日誌

有些需求須要 WebSocket 一直鏈接,好比 待辦事項主動提醒。若是其它操做新增了一條通知,當前用戶的通知條目應當自動變成 6,而不是下一次刷新完再更新。code

待辦事項主動提醒

因爲 dva 自己的特性,若是刷新頁面,dva 全部狀態容器中的值都會清空,與此同時 WebSocket 鏈接也會斷開,也就無法監聽服務端傳過來的數據。對象

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

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 的做用是監聽瀏覽器地址欄地址若是變成當前頁面 reptile/novel 就建立 WebSocket 鏈接,這樣就能保證每次進入這個頁面的時候都已鏈接 WebSocket。

對於 待辦事項主動提醒 那個需求,只需在佈局文件中的 subscriptions 中添加上述代碼便可。

相關文章
相關標籤/搜索