这主要是RxJs的最佳实践/方法问题,因为我的POC代码有效,但我对RxJs来说是全新的。
问题归结为.subscribe()
vs .publish().connect()
,因为它们似乎都做同样的事情。
在我的angular2应用程序中,我有一个按钮,它调用一个函数来记录用户,该函数调用我的服务中执行某些服务器端操作的函数,并返回一个URL以将用户重定向到。为了发起请求,我调用.subscribe()
以使observable开始生成值。我正在阅读一篇关于“冷与热可观测量”的文章,另一种方法是拨打.publish().connect()
而不是.subscribe()
。两种方法都有任何好处。
<a (click)="logout()">Logout</a>
注销功能如下所示:
logout.component.ts
logout() { this.authService.logout(); }
服务(实际注销)如下所示:
auth.service.ts
logout() : Observable<boolean> {
this.http.get(this.location.prepareExternalUrl('api/v1/authentication/logout'))
.map(this.extractData)
.catch(this.handleError)
.do((x: string) => { window.location.href = x; })
.subscribe(); // Option A -
return Observable.of(true);
}
auth.service.alternative.ts
logout() : Observable<boolean> {
this.http.get(this.location.prepareExternalUrl('api/v1/authentication/logout'))
.map(this.extractData)
.catch(this.handleError)
.do((x: string) => { window.location.href = x; })
.publish() // Option B - Make connectable observable
.connect(); // Option B - Cause the connectable observable to subscribe and produce my value
return Observable.of(true);
}
答案 0 :(得分:21)
subscribe()
和.publish().connect()
之间的区别在于他们订阅了源Observable。考虑以下Observable:
let source = Observable.from([1, 2, 3])
此Observable在订阅时向Observer发出所有值。因此,如果我有两个观察者,那么他们会按顺序接收所有值:
source.subscribe(val => console.log('obs1', val));
source.subscribe(val => console.log('obs2', val));
这将打印到控制台:
obs1 1
obs1 2
obs1 3
obs2 1
obs2 2
obs2 3
另一方面,调用.publish()
会返回ConnectableObservable
。这个Observable在它的构造函数中没有订阅它的源代码(在我们的例子中是source
)并且只保留它的引用。然后你可以订阅多个观察者,没有任何反应。最后,您致电connect()
,ConnectableObservable
订阅source
即开始发布值。这次已经有两个观察者订阅,所以它逐个向两个观察者发出值:
let connectable = source.publish();
connectable.subscribe(val => console.log('obs1', val));
connectable.subscribe(val => console.log('obs2', val));
connectable.connect();
打印到控制台:
obs1 1
obs2 1
obs1 2
obs2 2
obs1 3
obs2 3
答案 1 :(得分:4)
这会稍微回避你的问题,但你可能会发现它有用:
我不会从调用http
服务的流中返回不同的可观察流,因为这样做会使调用函数无法执行:
相反,我会这样做:
<强> auth.servive.ts 强>
logout() : Observable<string> {
return this.http.get(...).map(this.extractData)
.catch(this.handleError);
}
现在,调用代码可以使用生成的URL
执行任何操作<强> logout.component.ts 强>
logout(){
this.authService.logout().subscribe(
url => window.location.href = url,
err => {
/*todo: handle if error was thrown by authService.handleError*/
}
);
}