(記)在remax,小程式,react hooks中使用實時通訊

別人都叫我什麼發表於2020-10-23

1.建立一個wxsocket.js

import {
  connectSocket,
  onSocketOpen,
  onSocketClose,
  sendSocketMessage,
  onSocketMessage,
  getNetworkType,
  closeSocket,
  onNetworkStatusChange
} from 'remax/wechat';
class Websocket {
  constructor({ heartCheck, isReconnection }) {
    this.init = false;
    // 是否連線
    this.isConnect = false;
    // 當前網路狀態
    this.netWork = true;
    // 是否人為退出
    this.isClosed = false;
    // 心跳檢測頻率
    this.timeout = 3000;
    this.timeoutObj = null;
    // 當前重連次數
    this.connectNum = 0;
    // 心跳檢測和斷線重連開關,true為啟用,false為關閉
    this.heartCheck = heartCheck;
    this.isReconnection = isReconnection;
    this.wsUrl = "";
    this.onSocketOpened();
  }

  // 心跳重置
  reset () {
    clearTimeout(this.timeoutObj);
    return this;
  }

  // 心跳開始
  start () {
    let self = this;
    this.timeoutObj = setInterval(() => {
      sendSocketMessage({
        // 心跳傳送的資訊應由前後端商量後決定
        data: JSON.stringify({
          "beat": 'dj'
        }),
        success (res) {
          // console.log(res)
          // console.log("傳送心跳成功");
        },
        fail (err) {
          console.log(err);
          // this.reConnect(options)
          console.log('連線失敗');
          self.reset();
        }
      }).then();
    }, this.timeout);
  }

  // 監聽websocket連線關閉
  onSocketClosed (options) {
    onSocketClose(err => {
      console.log('當前websocket連線已關閉,錯誤資訊為:' + JSON.stringify(err));
      // 停止心跳連線
      if (this.heartCheck) {
        this.reset();
      }
      // 關閉已登入開關
      this.isConnect = false;
      // 檢測是否是使用者自己退出小程式
      if (!this.isClosed) {
        // 進行重連
        if (this.isReconnection) {
          this.reConnect(options);
        }
      }
    });
  }

  // 檢測網路變化
  onNetworkChange (options) {
    onNetworkStatusChange(res => {
      console.log('當前網路狀態:' + res.isConnected);
      if (!this.netWork) {
        this.isConnect = false;
        // 進行重連
        if (this.isReconnection) {
          this.reConnect(options);
        }
      }
    });
  }

  onSocketOpened (callBack) {
    onSocketOpen(res => {
      console.log('websocket已開啟');
      // 開啟已登入開關
      this.isConnect = true;
      // 傳送心跳
      if (this.heartCheck) {
        this.reset().start();
      }
      // 傳送登入資訊
      sendSocketMessage({
        // 這裡是第一次建立連線所傳送的資訊,應由前後端商量後決定
        data: JSON.stringify({
          "beat": 'dj'
        })
      }).then();
      // 開啟網路開關
      this.netWork = true;
      if (typeof callBack == "function") {
        callBack(res);
      }
    });
  }

  // 接收伺服器返回的訊息
  onReceivedMsg (callBack) {
    onSocketMessage(msg => {
      if (typeof callBack == "function") {
        callBack(msg);
      }
    });
  }

  // 建立websocket連線
  initWebSocket (options) {
    let self = this;
    this.wsUrl = options.url ? options.url : this.wsUrl;
    if (this.isConnect) {
      console.log("您已連線了");
    } else {
      // 檢查網路
      getNetworkType({
        success (res) {
          if (res.networkType !== 'none') {
            // 開始建立連線
            connectSocket({
              url: self.wsUrl,
              success (res) {
                if (typeof options.success == "function") {
                  options.success(res);
                }
              },
              fail (err) {
                if (typeof options.fail == "function") {
                  options.fail(err);
                  console.log('連線失敗');
                }
              }
            });
          } else {
            console.log('網路已斷開');
            self.netWork = false;
          }
        }
      }).then();
    }
  }

  // 傳送websocket訊息
  sendWebSocketMsg (options) {
    // console.log("send引數:", options)
    sendSocketMessage({
      data: options.data,
      success (res) {
        if (options.success && typeof options.success == "function") {
          options.success(res);
        }
      },
      fail (err) {
        if (options.fail && typeof options.fail == "function") {
          options.fail(err);
        }
      }
    }).then();
  }

  // 重連方法,會根據時間頻率越來越慢
  reConnect (options) {
    let timer, self = this;
    if (this.connectNum < 3) {
      timer = setTimeout(() => {
        this.initWebSocket(options);
      }, 3000);
      this.connectNum += 1;
    } else if (this.connectNum < 10) {
      timer = setTimeout(() => {
        this.initWebSocket(options);
      }, 10000);
      this.connectNum += 1;
    } else {
      timer = setTimeout(() => {
        this.initWebSocket(options);
      }, 450000);
      this.connectNum += 1;
    }
  }

  // 關閉websocket連線
  closeWebSocket () {
    closeSocket().then();
    this.isClosed = true;
    this.isConnect = false;
  }
}

const websocket = new Websocket({
  // true代表啟用心跳檢測和斷線重連
  heartCheck: true,
  isReconnection: true
});
export default websocket;

2.使用

import websocket from "../../utils/wxsocket";
  React.useEffect(() => {
    if (token) {
      const wsUrl = process.env.NODE_ENV === 'development' ? `wss://test.onemorecar.cn/ws/notify?token=${token}` : `wss://tt.onemorecar.cn/ws/notify?token=${token}`;
  
      if (!websocket.init) {
        websocket.initWebSocket({ url: wsUrl });
        websocket.onSocketClosed({
          url: wsUrl
        })
        websocket.onNetworkChange({
          url: wsUrl
        })
        websocket.onReceivedMsg(res => {
          console.log('app.js收到伺服器內容:' + res.data);
          const { msg, count, status } = JSON.parse(res.data);
          if (count) {
            notify.setNotify(count);
          }
        });
      }
    }
    },[])

相關文章