Rxjs - 无法将冷观察变为热点

时间:2017-02-01 19:43:18

标签: angular rxjs reactive-programming rxjs5

所以我使用Angular 2并努力使HTTP请求可观察,以便在多个观察者之间共享。更具体地说,我想分享所有的响应类型,包括错误。

我尝试过这样:

return this._http.request(new Request(options))
  .map((res: Response) => this.refreshToken(res))
  .share()

然后

this.data.request()
  .map((response: Response) => (new financeiro.FetchCompletedAction(response)))
  .catch((error: any) => {
    console.log('lancamento-effects:');
    return Observable.of(new feedback.HttpRequestFailedAction(["Erro ao inserir lançamento"]))
  })

上面的代码用于发送错误操作,最终在用户屏幕上显示错误消息。

实际上这发生了两次......

enter image description here

它也会在控制台上打印两次。

enter image description here

3 个答案:

答案 0 :(得分:2)

以下是一些代码(Plunkr):

@Component({
  selector: 'my-app',
  template: `
    <button (click)="subscribe()">Subscribe</button>
  `
})
export class AppComponent {
  obs: Observable<any>;

  constructor(private http: Http) {
    // Create the observable ONCE + Share.
    this.obs = this.http.get('https://httpbin.org/get')
      .do(() => console.log('***SIDE EFFECT***'))
      .mapTo('***RESULT***')
      .share();
  }

  subscribe() {
    // Subscribe to the same observable TWICE.
    this.obs.subscribe(val => console.log('subs1', val));
    this.obs.subscribe(val => console.log('subs2', val));
  }
}

以下是控制台显示的内容:

***SIDE EFFECT***
subs1 ***RESULT***
subs2 ***RESULT***

一个副作用(即HTTP请求),两个订阅。

这就是你要找的东西吗?

答案 1 :(得分:0)

确保每个订阅者订阅相同的热点可观察对象。每次打电话:

return this._http.request(new Request(options))
  .map((res: Response) => this.refreshToken(res))
  .share()

您正在从冷观察中创建一个新的热观察。

假设上面的代码包含在一个名为foo()的函数中的示例:如果执行以下操作,您将创建2个热可观察对象和2个http请求:

foo().subscribe(...)
foo().subscribe(...)

以下只会创建一个热的可观察(和单个http请求):

let hotObs = foo();
hotObs.subscribe(...)
hotObs.subscribe(...);

答案 2 :(得分:0)

您需要了解冷/热可观察对象。

冷的Observable 是一个Observable,它在每次订阅时都会重新执行其订阅处理程序:

const cold = new Observable(function subscribe(observer) {
  console.log('subscribed');
  observer.next(Math.random());
  observer.complete();
});
// > subscribed
// sub 1: 0.1231231231231
cold.subscribe((num) => console.log('sub 1:', num));
// > subscribed
// sub 2: 0.09805969045
cold.subscribe((num) => console.log('sub 2:', num));

热可观察是可观察的源(冷或其他),在源和订阅者之间具有主题。订阅热的Observable时,订阅将在内部透明地路由到内部Subject,并且Subject订阅了源Observable。这样可以确保源Observable仅具有一个订阅者(主题),并且主题与许多订阅者共享源的值:

const cold = new Observable(function subscribe(observer) {
  console.log('subscribed');
  observer.next(Math.random());
  observer.complete();
});

const hot = cold.publish();
hot.subscribe((num) => console.log('sub 1:', num));
hot.subscribe((num) => console.log('sub 2:', num));
hot.connect(); // <-- this subscribes the inner Subject to the cold source
// > subscribed
// > sub 1: 0.249848935489
// > sub 2: 0.249848935489

您可以通过多播使Observable成为热点,该多播具有一个函数,该函数可在连接主题时返回要使用的主题。为方便起见(例如发布),多播也有一些变体,可以创建特定类型的主题。 publish()multicast(() => new Subject())

的一种便捷方法

除了connect()(使内部Subject订阅源并返回基础Subscription)之外,您还可以调用refCount(),后者返回Observable。由refCount()返回的Observable订阅一次后,它将在内部自动调用connect(),后续的订阅将不会重新连接。当所有订阅者都取消订阅时,refCount将自动从源中取消订阅内部主题。 share()source.publish().refCount()的一种便捷方法。

所以,两者的工作方式相同,

const a = Rx.Observable.create().share();
const b = new Rx.Subject();