只有一个订阅者从服务器接收响应

Posted

技术标签:

【中文标题】只有一个订阅者从服务器接收响应【英文标题】:Only one subscriber receives responses from server 【发布时间】:2016-12-22 03:32:04 【问题描述】:

使用 RxJs 和 WebSockets,我创建了几个服务,它们应该从服务器接收数据并将其发送给我程序中服务的订阅者。当我只有一项服务时,没有问题,但在创建第二项服务后,第一项服务不再收到响应。我如何确保它确实有效?

这是我的 WebSocket 服务:

import  Injectable  from '@angular/core';
import * as Rx from 'rxjs/Rx';

@Injectable()
export class WebSocketService 
private subject: Rx.Subject<MessageEvent>;

public connect(url): Rx.Subject<MessageEvent> 
    if (!this.subject) 
        this.subject = this.create(url);
    
    return this.subject;


private create(url): Rx.Subject<MessageEvent> 
    let ws = new WebSocket(url);

    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);


这是我的倒计时服务:

import  Injectable  from '@angular/core';
import  Observable, Subject  from 'rxjs/Rx';
import WebSocketService  from './websocket.service';

const AUCTION_URL = 'ws://localhost:9999';

export interface Countdown 
days: number,
hours: number,
minutes: number,
seconds: number


@Injectable()
export class CountdownService 
public countdowns: Subject<Countdown>;

constructor(wsService: WebSocketService) 
    this.countdowns = <Subject<Countdown>>wsService
        .connect(AUCTION_URL)
        .map((response: MessageEvent): Countdown => 
            let data = JSON.parse(response.data);
            return 
                days: data.days,
                hours: data.hours,
                minutes: data.minutes,
                seconds: data.seconds
            
        );


其他服务的实现方式与倒计时服务相同,但具有其他变量。

感谢任何帮助,谢谢。

【问题讨论】:

【参考方案1】:

服务是否跨多个组件使用?我会检查该服务是否只被实例化一次。

您还可以通过将 share 运算符添加到 observable create 来确保:

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);
        ).share()

【讨论】:

感谢您的回复。当我这样做时,我收到此错误:(SystemJS)wsService 未定义(...) 需要使用this.wsService 改变了,现在我得到这个错误:(SystemJS)无法读取未定义的属性“连接”(…) 我认为分享部分需要在this.subject = this.create(url).share(); @echonax 这给了我一个错误:app/websocket.service.ts(10,13): error TS2322: Type 'Observable' is notassignable to type 'Subject' . “Observable”类型中缺少属性“观察者”。

以上是关于只有一个订阅者从服务器接收响应的主要内容,如果未能解决你的问题,请参考以下文章

当响应不包含媒体类型标头时,Spring webclient 抛出“仅允许一个连接接收订阅者”

从服务器接收响应时出错?

Android GCM 服务器错误:设备订阅已过期

从 Rest 服务接收 excel 文件作为 javascript 响应

qpid proton url,用于从给定订阅(主题)接收消息

Android & NodeMCU,从服务器接收响应不能正常工作?