Angular / RxJS多播可观察的

时间:2019-01-15 00:38:20

标签: angular rxjs observable reactive-programming

我有一个HTTP请求,希望将结果共享给多个组件。 HTTP请求当然会返回Observable。我希望多个组件能够订阅此消息而不会触发其他HTTP请求。

我在组件中使用Subject来完成此任务,该组件按需发出HTTP请求,并具有另一种订阅主题的方法。  虽然这样做有效-似乎过于矫kill过正,并且确实有更好的方法可以做到这一点。

主题服务

@Injectable()
export class EventService {
    subject: BehaviorSubject<any> = new BehaviorSubject<any>(Observable.create());

    constructor(private api: Api) {}

    fetch = () => {
        this.subject.next(
            this.api.getUsers().pipe(share())
        );
    };

    listen = (): Observable<any> => {
        return this.subject.asObservable();
    };
}

和一个订户

@Injectable
export class EventListenerA {
    constructor(private eventService: EventService){
        eventService.fetch(); // make initial call
        eventService.listen().subscribe(o => {
             o.subscribe(httpResponse => {
                 //do something with response
             })
        });
    }
}

和第二位订阅者

@Injectable
export class EventListenerB {
    constructor(private eventService: EventService){
        eventService.listen().subscribe(o => {
             o.subscribe(httpResponse => {
                 //do something else with response
             })
        });
    }
}

当我从管道链中删除share()时,会发出多个网络请求。是否有更优雅/正确的方法将可观察对象传递到next的{​​{1}}?或完全是另一种模式

1 个答案:

答案 0 :(得分:2)

您应在使用ReplaySubject()时不要给它一个初始值。这样,当组件订阅listen()时,它将等待,直到有可用数据为止。

不需要与其他组件共享 HTTP。只需订阅HTTP请求,然后将值发送到ReplaySubject()。任何侦听的组件都将接收数据。

@Injectable()
export class EventService {
     private _events: ReplaySubject<any> = new ReplaySubject(1);

     public constructor(private _api: ApiService) {}

     public fetch() {
         this.api.getUsers().subscribe(value => this._events.next(value));
     }

     public listen() {
         return this._events.asObservable();
     }
 }

 @Injectable
 export class EventListenerA {
     constructor(private eventService: EventService){
          eventService.fetch();
          eventService.listen().subscribe(o => {
              // prints user data
              console.log(o); 
          });
     }
}

每次有人呼叫eventService.fetch()时,都会触发HTTP请求。如果您只想执行一次此请求,则可以从服务构造函数或应用程序中仅发生一次的其他位置(即模块构造函数)调用fetch()