Angular HTTP调用订阅了关闭主题的主题

时间:2018-03-02 09:04:59

标签: angular rxjs

我有两个可以获取给定对象的服务:用于获取完整列表的初始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));
}

我没有任何问题,所有项目都被正确获取。

我想知道为什么这两个版本不同,为什么在第一种情况下,主题最终会被关闭。

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

这是正确的行为。当您使用.subscribe(subject)时,您订阅了所有三种类型的通知。所有主题都是观察者,所以它与编写以下内容相同:

.subscribe(
  v => subject.next(v),
  err => subject.error(err),
  () => subject.complete()
);

因此,如果您仅使用.subscribe(item => subject.next(item)),那么您只会传递next次通知,而不会传递errorcomplete次通知,因此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';