我有两个可以获取给定对象的服务:用于获取完整列表的初始HTTP调用,以及用于实时更新新元素的websocket通知。
我想将两个调用连接到同一个observable,以便显示页面不知道后端。
有致电:
private getInitialData(subject: Subject<any>) {
this._http.get<Array<any[]>>(`/call/to/backend`)
.flatMap(items => items)
.subscribe(subject);
}
private listenNewData(subject: Subject<any>) {
this.websocketService.listen('/some/ws/topic')
.subscribe(subject);
}
private initialize() {
const subject = new Subject<any>();
this.dataService.getInitialData(subject);
this.listenNewData(subject);
subject.subscribe(item => this.items.push(item))
}
当以这种方式注册主题时,似乎主题实际上在HTTP解析后关闭,并且没有向该主题发送websocket通知。
但是,在订阅功能上使用回调注册时:
private getInitialData(subject: Subject<any>) {
this._http.get<Array<any[]>>(`/call/to/backend`)
.flatMap(items => items)
.subscribe(item => subject.next(item));
}
private listenNewData(subject: Subject<any>) {
this.websocketService.listen('/some/ws/topic')
.subscribe(item => subject.next(item));
}
我没有任何问题,所有项目都被正确获取。
我想知道为什么这两个版本不同,为什么在第一种情况下,主题最终会被关闭。
感谢您的帮助。
答案 0 :(得分:2)
这是正确的行为。当您使用.subscribe(subject)
时,您订阅了所有三种类型的通知。所有主题都是观察者,所以它与编写以下内容相同:
.subscribe(
v => subject.next(v),
err => subject.error(err),
() => subject.complete()
);
因此,如果您仅使用.subscribe(item => subject.next(item))
,那么您只会传递next
次通知,而不会传递error
或complete
次通知,因此subject
永远不会完成。< / p>
答案 1 :(得分:1)
为什么不使用forkjoin?
const apiCalls = [
this._http.get<Array<any[]>>(`/call/to/backend`),
this.websocketService.listen('/some/ws/topic')
];
forkJoin(apiCalls)
.subscribe((results: Array<any>) => {
// results[0] = call from api call 1
// results[1] = call from api call 2
// so combine results: combined = results[0] + results[1]
this.items.push(combined)
}, (error) => console.log(error));
这样,当两个结果都回来时,您将在订阅中,您可以使用这两个结果而不是组合主题。
不要忘记添加导入:
import {forkJoin} from 'rxjs/observable/forkJoin';
import {Observable} from 'rxjs/Observable';