我有一个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}}?或完全是另一种模式
答案 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()
。