Angular Observable等待websocket消息响应超时

时间:2019-02-26 09:22:34

标签: angular websocket rxjs observable

我正在Angular应用程序中编写Websocket服务。 现在,我想向服务器发送一条消息,并等待确定的时间以进行响应。 为了识别响应,我使用sync-和sync-response-ID。

    import { Injectable } from '@angular/core';
    import {webSocket, WebSocketSubject} from "rxjs/webSocket";
    import {of, from, Observable, timer } from "rxjs";
    import {share, filter, takeUntil} from "rxjs/operators";

    class WsMessage{
      Id: number;
      TimeStamp: Date;
      ResponseId: number;
      MessageData: string;
    }

    class MessageQueue{
      Message: WsMessage;
      TimeStamp: Date;
      SyncId: number;
    }

@Injectable({
  providedIn: 'root'
})
export class WsService{
  // Any message has a maximum lifetime of 10 mimnutes.
  private readonly MaxMessageQueueTime = 600;
  private clearQueueTimer: any;
  private messageQueue: Array<MessageQueue> = new Array<MessageQueue>(); 
  private socket: WebSocketSubject<WsMessage>;
  private idGenerator: number;

  constructor(){
        // Check every 30s for clearing old messages.
    this.clearQueueTimer = setInterval(() =>{
      if(this.messageQueue){
        let maxTime = new Date();
        maxTime = new Date(maxTime.setTime(maxTime.getTime() + 
(this.MaxMessageQueueTime * 1000)));
        this.messageQueue= this.messageQueue.filter(m => m.TimeStamp <= maxTime);
  }
}, 30000)
  }

  public Init(url: string){
      this.idGenerator = 0;
      if(this.socket!= null) {
        this.socket.unsubscribe();
        this.socket = null;
      }

      this.socket = webSocket<WsMessage>({
        url: url,
        openObserver: {
          next: value => {
            console.log(value);
          }
        }
      });
      this.socket.subscribe(msg => {
        if(msg != null && msg.Id > 0 && this.messageQueue.filter(i => i.SyncId == msg.Id).length == 0){
          let m = new MessageQueue();
          m.SyncId = msg.Id;
          m.Message = msg;
          m.TimeStamp = new Date();  
          this.messageQueue.push(m);            
        }
        console.log("msg received: " + msg);
      },
      error1 => {
        console.log("error received: " + error1);
      },
      () => {
        console.log("connection closed!");
      });      
    }
    public sendAndWait(message: WsMessage, timeout: number): Observable<WsMessage>{
    if(message== null){
      return null;
    }
    if(this.socket == null){
      return null;
    }
    let id = this.idGenerator++;
    message.Id = id;

    this.socket.next(message);
    let obs = from(this.messageQueue).pipe(share());
    let timeoutTimer = timer(5000);
    let result = obs.pipe(filter(m => m.ResponseId == id)).pipe(takeUntil(timeoutTimer)).pipe(map(m => m.Message)).pipe(share());
    result.subscribe(value => {
      this.messageQueue= this.messageQueue.filter(m => m.ResponseId != value.Id)
});
    return result;
  }    
}

我不确定给定的过程是否安全并且没有泄漏? 对于未取消订阅的订阅,我应该小心吗?

谢谢!

更新:

  • 添加了一个BehaviourSubject,以便任何人都可以订阅收到的消息
  • 添加了ngDestroy来取消订阅套接字
  • 创建了stackblitz示例以提高可读性

Stackblitz example

0 个答案:

没有答案