websocket 參考代碼


網上找的websocket的前期參考代碼,存一份,侵刪

import {Injectable} from '@angular/core';
import {interval, Subject} from 'rxjs';

/**
 * websocket服務
 * @author LiQun
 * @date 2019/1/25
 */
@Injectable({
  providedIn: 'root'
})
export class WebsocketService {
  messageSubject;                                 // subject對象,用於發送事件
  private url;                                    // 默認請求的url
  private webSocket: WebSocket;                   // websocket對象
  connectSuccess = false;                         // websocket 連接成功
  period = 60 * 1000 * 10;                        // 10分鍾檢查一次
  serverTimeoutSubscription = null;               // 定時檢測連接對象
  reconnectFlag = false;                          // 重連
  reconnectPeriod = 5 * 1000;                     // 重連失敗,則5秒鍾重連一次
  reconnectSubscription = null;                   // 重連訂閱對象
  runTimeSubscription;                            // 記錄運行連接subscription
  runTimePeriod = 60 * 10000;                     // 記錄運行連接時間

  constructor() {
    this.messageSubject = new Subject();
    console.log('開始心跳檢測');
    // 進入程序就進行心跳檢測,避免出現開始就連接中斷,后續不重連
    this.heartCheckStart();
    this.calcRunTime();
  }

  /**
   * 發送消息
   * @author LiQun
   * @date 2019/1/22
   * @param message 發送消息
   */
  sendMessage(message) {
    this.webSocket.send(message);
  }

  /**
   * 創建新連接
   * @author LiQun
   * @date 2019/1/22
   * @param url 要連接的url
   */
  connect(url) {
    if (!!url) {
      this.url = url;
    }
    // 創建websocket對象
    this.createWebSocket();
  }

  /**
   * 創建連接
   * @author LiQun
   * @date 2019/1/22
   */
  createWebSocket() {
    // 如果沒有建立過連接,才建立連接並且添加時間監聽
    this.webSocket = new WebSocket(this.url);
    // 建立連接成功
    this.webSocket.onopen = (e) => this.onOpen(e);
    // 接收到消息
    this.webSocket.onmessage = (e) => this.onMessage(e);
    // 連接關閉
    this.webSocket.onclose = (e) => this.onClose(e);
    // 異常
    this.webSocket.onerror = (e) => this.onError(e);
  }

  /**
   * 連接打開
   * @author LiQun
   * @date 2019/1/22
   * @param e 打開事件
   */
  onOpen(e) {
    console.log('websocket 已連接');
    // 設置連接成功
    this.connectSuccess = true;
    // 如果是重連中
    if (this.reconnectFlag) {
      // 1.停止重連
      this.stopReconnect();
      // 2.重新開啟心跳
      this.heartCheckStart();
      // 3.重新開始計算運行時間
      this.calcRunTime();
    }
  }

  /**
   * 接受到消息
   * @author LiQun
   * @date 2019/1/22
   * @param event 接受消息事件
   */
  onMessage(event) {
    console.log('接收到的消息', event.data);
    // 將接受到的消息發布出去
    const message = JSON.parse(event.data);
    console.log('接收到消息時間', new Date().getTime());
    this.messageSubject.next(message);
  }

  /**
   * 連接關閉
   * @author LiQun
   * @date 2019/1/22
   */
  private onClose(e) {
    console.log('連接關閉', e);
    this.connectSuccess = false;
    this.webSocket.close();
    // 關閉時開始重連
    this.reconnect();
    this.stopRunTime();
    // throw new Error('webSocket connection closed:)');
  }

  /**
   * 連接異常
   * @author LiQun
   * @date 2019/1/22
   */
  private onError(e) {
    // 出現異常時一定會進onClose,所以只在onClose做一次重連動作
    console.log('連接異常', e);
    this.connectSuccess = false;
    // throw new Error('webSocket connection error:)');
  }

  /**
   * 開始重新連接
   * @author LiQun
   * @date 2019/1/22
   */
  reconnect() {
    // 如果已重連,則直接return,避免重復連接
    if (this.connectSuccess) {
      this.stopReconnect();
      console.log('已經連接成功,停止重連');
      return;
    }
    // 如果正在連接中,則直接return,避免產生多個輪訓事件
    if (this.reconnectFlag) {
      console.log('正在重連,直接返回');
      return;
    }
    // 開始重連
    this.reconnectFlag = true;
    // 如果沒能成功連接,則定時重連
    this.reconnectSubscription = interval(this.reconnectPeriod).subscribe(async (val) => {
      console.log(`重連:${val}次`);
      const url = this.url;
      // 重新連接
      this.connect(url);
    });
  }

  /**
   * 停止重連
   * @author LiQun
   * @date 2019/1/22
   */
  stopReconnect() {
    // 連接標識置為false
    this.reconnectFlag = false;
    // 取消訂閱
    if (typeof this.reconnectSubscription !== 'undefined' && this.reconnectSubscription != null) {
      this.reconnectSubscription.unsubscribe();
    }
  }

  /**
   * 開始心跳檢測
   * @author LiQun
   * @date 2019/1/22
   */
  heartCheckStart() {
    this.serverTimeoutSubscription = interval(this.period).subscribe((val) => {
      // 保持連接狀態,重置下
      if (this.webSocket != null && this.webSocket.readyState === 1) {
        console.log(val, '連接狀態,發送消息保持連接');
      } else {
        // 停止心跳
        this.heartCheckStop();
        // 開始重連
        this.reconnect();
        console.log('連接已斷開,重新連接');
      }
    });
  }

  /**
   * 停止心跳檢測
   * @author LiQun
   * @date 2019/1/22
   */
  heartCheckStop() {
    // 取消訂閱停止心跳
    if (typeof this.serverTimeoutSubscription !== 'undefined' && this.serverTimeoutSubscription != null) {
      this.serverTimeoutSubscription.unsubscribe();
    }
  }

  /**
   * 開始計算運行時間
   * @author LiQun
   * @date 2019/1/25
   */
  calcRunTime() {
    this.runTimeSubscription = interval(this.runTimePeriod).subscribe(period => {
      console.log('運行時間', `${period}分鍾`);
    });
  }

  /**
   * 停止計算運行時間
   * @author LiQun
   * @date 2019/1/25
   */
  stopRunTime() {
    if (typeof this.runTimeSubscription !== 'undefined' && this.runTimeSubscription !== null) {
      this.runTimeSubscription.unsubscribe();
    }
  }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM