【问题标题】:Angular / RxJS Multicasting Observable of ObservableAngular / RxJS 多播 Observable 的 Observable
【发布时间】:2019-06-09 00:19:44
【问题描述】:

我有一个 HTTP 请求,我想将其结果共享给多个组件。 HTTP 请求当然会返回一个Observable。我希望多个组件能够订阅它而不触发额外的 HTTP 请求。

我在一个组件中使用Subject 实现了这一点,该组件根据需要发出 HTTP 请求,并有另一种订阅主题的方法。 虽然这行得通 - 这似乎有点矫枉过正,而且肯定有更好的方法来做到这一点。

学科服务

@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() 时,会发出多个网络请求。有没有更优雅/正确的方法将 observable 传递给 nextSubject ?或者完全是另一种模式

【问题讨论】:

    标签: angular rxjs observable reactive-programming


    【解决方案1】:

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

    无需与其他组件共享 HTTP observable。只需订阅 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()

    【讨论】:

    • 是的,这就是门票 - 内部订阅是一种赠品的味道 - 我很惊讶我从未在我找到的任何教程中看到 ReplaySubject。谢谢!
    猜你喜欢
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-15
    • 2019-12-25
    • 2018-01-17
    • 2017-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多