Websocket 事件仅被一个组件捕获

Posted

技术标签:

【中文标题】Websocket 事件仅被一个组件捕获【英文标题】:Websocket event is being catched only by one component 【发布时间】:2019-01-15 13:47:25 【问题描述】:

我在 Angular7 中有一个 websocket 服务

import  environment  from './../../../environments/environment.prod';
import  Injectable  from '@angular/core';
import * as Rx from 'rxjs';
import map from 'rxjs/operators';
@Injectable()
export class WsService
public wsMessages: Rx.Subject<any>;

public connect(url): Rx.Subject<MessageEvent> 
    if(!this.subject)
        this.subject = this.create(url);
        console.log("Websocket (Dashboard) successfully connected to : ", url);
     
    return this.subject;


private create(url): Rx.Subject<MessageEvent> 
    let ws = new WebSocket(
        url,
        [`Bearer`, `$this.token.substring(7)`] 
        );
    let observable = Rx.Observable.create(
        (obs: Rx.Observer<MessageEvent>) => 
            ws.onmessage = obs.next.bind(obs);
            ws.onerror = obs.error.bind(obs);
            ws.onclose = obs.complete.bind(obs);
            return ws.close.bind(ws);
        
    )

    let observer = 
        next: (data: Object) => 
            if(ws.readyState === WebSocket.OPEN) 
                ws.send(JSON.stringify(data));
            
        
    

    return Rx.Subject.create(observer, observable);

private token: string;
constructor()
   this.token = JSON.parse(localStorage.getItem('user')).token
    this.wsMessages = <Rx.Subject<any>>
    this.connect(`$environment.websocketUrl/dashboard/ws`)
    .pipe(
        map((response: MessageEvent): any =>
            let data = JSON.parse(response.data);
            return data;
        )
    )

private subject: Rx.Subject<MessageEvent>;

我有多个订阅wsMessages的组件

 this.ws.wsMessages.subscribe(msg => 
    this.catchWebSocketEvents(msg)
    console.log("LeftBarSocket : ", msg);
  )

事件只打印在一个组件上,我需要很多组件来监听这些 ws 事件。

【问题讨论】:

可能那时其他组件已经是destroyed了。另外,我建议您将BehaviorSubject 用于保留先前数据的功能,subject 在发出后会丢失数据(检查是否是您的情况) 组件没有被破坏,它可能与多播有关,但我不明白如何使用它。 我没有看到 wsMessages 在哪里被赋值? 【参考方案1】:

好吧,在对该主题进行了一些阅读之后,我发现有一个share() 函数允许多个订阅者共享一个源。

解决方案在这里:

 const observable = Rx.Observable.create(
        (obs: Rx.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);
        
    ).pipe(
        share()
    )

只需将.pipe(share()) 添加到正在创建的可观察对象中。

【讨论】:

以上是关于Websocket 事件仅被一个组件捕获的主要内容,如果未能解决你的问题,请参考以下文章

什么项目将使用 websocket 而不是 webrtc?

Vue.js 在 websocket onmessage 事件中更新 html

从 REST 和服务器与客户端事件的角度理解 websocket

Django用websocket实现聊天室之筑基篇

如何根据第一个组件收到的 websocket 事件更新第二个组件中的内容?

多个组件捕获保存存储事件