Angular4 Websocket rxjs重新连接和onError [英] Angular4 Websocket rxjs Reconnect and onError

查看:297
本文介绍了Angular4 Websocket rxjs重新连接和onError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎有几个类似的问题,但是几天后我找不到正确的答案.我的问题是如何知道服务器是否已关闭websocket,以及如何尝试重新连接.我已经看到了几个示例,但是当我想实现在更改视图时从客户端关闭websocket的功能时,它们都无法正常工作.

It looks like there are several similar questions but after several days I do not find the proper answer. My question is how to know if the server has closed the websocket and how to try to reconnect. I have seen several examples but none of them worked properly when I wanted to implement the fonctionality of closing the websocket from the client when I change the view.

然后我发现了这个示例,它是到目前为止,我所见过的最好的功能,并且进行了一些小的修改,就能够添加一个效果很好的close函数.

Then I found this example which it's the best one I have seen so far, and with a small modifications I was able to add a close function which works quite well.

从客户端关闭websocket不再是问题,但是,我不知道何时服务器关闭了websocket ,以及如何再次重新连接 .

Closing the websocket from the client is not a problem anymore, however, I am not able to know when the websocket is closed by the server and how to reconnect again.

我的代码与非常相似问题,但我要求另一件事.另外,我在重新使用websocket时遇到问题,直到在我放置的链接中看到他们谈论的共享功能为止,因此在我发布的课程中,websocket服务和使用websocket服务的服务被合并为一个

My code is very similar to this question but I am asking for a different thing. Also, I had problems re-using the websocket until I saw the share function that they talk in the link I put, so in the class I have posted, the websocket service and the service which used the websocket service are the merged in one

我的websocket服务

My websocket service

import { Injectable } from '@angular/core';
import { Observable, Observer, Subscription } from 'rxjs';
import { Subject } from 'rxjs/Subject';

import { ConfigService } from "../config.service";

@Injectable()
export class WSEtatMachineService {
    public messages: Subject<any>  = new Subject<any>();
    private url: string = '';
    static readonly ID = 'machine';

    private _subject: Subject<MessageEvent>;
    private _subjectData: Subject<number>;
    private _ws: any;

    constructor(private configService: ConfigService) {
        console.log('constructyor ws machine service')
        this.setUrl(WSEtatMachineService.ID)
    }

    public setUrl(id:string) {
        const host = this.configService.getConfigReseau().ipServer;
        const port = this.configService.getConfigReseau().portServer;
        this.url = `ws://${host}:${port}/` + id 
    }

    public connect() {
        console.log('connect ws machine service ', this.url)
        this.messages = <Subject<any>>this._connect(this.url)
            .map((response: any): any => {
                console.log('ws etat machine service: ', response)
                return JSON.parse(response.data);
            })

    }

    public close() {
        console.log('on closing WS');
        this._ws.close()
        this._subject = null
    }

    public send(msg: any) {
        this.messages.next(JSON.stringify(msg));
    }

    // Private methods to create the websocket

    public _connect(url: string): Subject<MessageEvent> {
        if (!this._subject) {
            this._subject = this._create(url);
        }
        return this._subject;
    }

    private _create(url: string): Subject<MessageEvent> {
        this._ws = new WebSocket(url);

        let observable = Observable.create(
            (obs: Observer<MessageEvent>) => {
                this._ws.onmessage = obs.next.bind(obs);
                this._ws.onerror   = obs.error.bind(obs);
                this._ws.onclose   = obs.complete.bind(obs);
                return this._ws.close.bind(this._ws);
            }).share();

        let observer = {
            next: (data: Object) => {
                if (this._ws.readyState === WebSocket.OPEN) {
                    this._ws.send(JSON.stringify(data));
                }
            }
        };

        return Subject.create(observer, observable);
    }
} // end class 

然后在我要做的组件中

constructor( private wsMachineService: WSMachineService) { ... }

ngOnInit() { 
...
this.wsMachineService.connect();
    // connexion du web socket
    this.wsMachineService.messages.subscribe(
      machine => {
        console.log(" wsMachineService open and alive", machine);

      },
      err => {
        // This code is never executed
        console.log(" wsMachineService closed by server!!", err);
      }
    );

}

ngOnDestroy() {
    //let tmp = this.synoptiqueSocketSubscription.unsubscribe();
    this.wsMachineService.messages.unsubscribe();
    this.wsMachineService.close()
}

我想我在_create函数中缺少某些内容,因为我试图抓住connect函数的主题,但是它不起作用.

I guess I'm missing something in the _create function because I try to do a catch in the subject of the connect function and it does not work.

关于如何知道它是否已关闭并尝试重新连接的任何想法?

Any ideas of how I can know if it is being closed and try to reconnect again?

谢谢

我认为我的问题与主题/可观察对象有关,因为我无法完全控制它们.我有一个旧的方法,我可以知道服务器何时死机,并试图每X秒重新连接一次,但是不幸的是,由于无法访问websocket对象,我无法从客户端关闭连接.我也添加了代码:

I think my problem is related to the subject / observables as I do not control them totally. I had an old approach where I could know when the server was dead and it was trying to reconnect each X seconds but unfortunately, I wasn't able to close the connection from the client as I didn't have access to the websocket object. I add the code as well:

  public messages: Observable<any>;
  private ws: Subject<any>;
  private url: string;
  public onclose = new Subject();

  public connect(urlApiWebSocket: string): Observable<any> {
    if (this.messages && this.url === urlApiWebSocket) {
      return this.messages;
    }
    this.url = urlApiWebSocket;
    this.ws = Observable.webSocket({
      url: urlApiWebSocket,
      closeObserver: this.onclose
    });
    return this.messages = this.ws.retryWhen(errors => errors.delay(10000)).map(msg => msg).share();
  }

  send(msg: any) {
    this.ws.next(JSON.stringify(msg));
  }

让我们看看是否有任何方法可以将两种解决方案结合起来.

Let's see if we have any way to combine both solutions.

推荐答案

好吧,我找到了一种方法.我在Observable.websocket中使用了旧方法

Well, I found a way. I'm using the old approach with Observable.websocket

@Injectable()
export class WSMyService {
    private url: string = '';
    static readonly ID = 'mytestwebsocket';
    readonly reload_time = 3000;

    public messages: Observable<any>;
    private ws: Subject<any>;
    public onclose = new Subject();
    constructor(private configService: ConfigService) {
        console.log('constructor ws synop service')
        this.setUrl(WSActionFrontService.ID)
    }

    public setUrl(id:string) {
        ...
        this.url = `ws://${host}:${port}/` + id 
    }

    public connect(): Observable<any> {
      this.ws = Observable.webSocket({
        url: this.url,
        closeObserver: this.onclose
      });
      return this.messages = this.ws.retryWhen(errors => errors.delay(this.reload_time)).map(msg => msg).share();
    }

    send(msg: any) {
      this.ws.next(JSON.stringify(msg));
    }

    public close() {
        console.log('on closing WS');
        this.ws.complete();
    }

当我使用它时:

constructor(
    private wsMyService: WSMyService,

ngOnInit():
  ...
  this.mySocketSubscription = this.wsMyService.connect().subscribe(message => {
 ... }
  this.wsMyService.onclose.subscribe(evt => {
  // the server has closed the connection
  })

ngOnDestroy() {

    this.wsMyService.close();
    this.mySocketSubscription.unsubscribe();
    ...
}

看起来我要做的就是调用complete()函数,该函数告知服务器客户端已完成. 我敢肯定有更好的方法,但这是我发现的唯一对我有用的方法.

Looks like all I had to do was to call the function complete() which tells the server that the client has finished. I'm sure there is a better way, but this is the only one I found that works for me.

谢谢您的帮助.

这篇关于Angular4 Websocket rxjs重新连接和onError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆