问题
我订阅了两次httpClient.get observable。但是,这意味着我的调用会被执行两次。这是为什么?
证明
对于我做的每个订阅(),我在登录页面中得到另一行。
代码(来自登录页面按钮的onSubmit())
var httpHeaders = new HttpHeaders()
.append("Authorization", 'Basic ' + btoa(this.username + ':' + this.password));
var observable = this.httpClient.get('api/version/secured', { headers: httpHeaders});
observable.subscribe(
() => {
console.log('First request completed');
},
(error: HttpErrorResponse) => {
console.log('First request error');
}
);
observable.subscribe(
() => {
console.log('Second request completed');
},
(error: HttpErrorResponse) => {
console.log('Second request error');
}
);
控制台
zone.js:2935 GET http://localhost:4200/api/version/secured 401 (Unauthorized)
login.component.ts:54 First request error
zone.js:2935 GET http://localhost:4200/api/version/secured 401 (Unauthorized)
login.component.ts:62 First request error
无关背景
我有一个LogonService对象来处理我的登录功能。它包含一个布尔变量,显示我是否登录。每当我调用login函数时,它都会订阅httpClient.get的observable,将login变量设置为true或false。但是login函数也返回了observable,它被订阅了。花了我一些时间将双重请求链接到双重订阅。如果有更好的方法来跟踪登录而不是通过变量,请告诉我!我正在努力学习角度:)
答案 0 :(得分:13)
尝试在HttpClient.get
的结果上使用share
运算符,如下所示:
var observable = this.httpClient.get('api/version/secured', { headers: httpHeaders })
.pipe(share());
您需要在脚本之上添加以下导入:
import { share } from 'rxjs/operators';
share
运算符生成可观察的hot
,即在订阅者之间共享。但是还有更多内容,我建议this article深入了解(你当然也可以谷歌hot vs cold observables
来寻找更多信息)。
答案 1 :(得分:2)
您的观察结果很冷:
如果创建了通知的生产者,则observable很冷 只要观察者订阅了观察者。例如,a 计时器可观察是冷的;每次订阅时,都会有新的订阅 计时器已创建。
您需要multicast
您的Observable,或换句话说,让它变热:
如果其通知的制作者不是,则观察者很热 每次观察者订阅观察者时都会创建。对于 例如,使用fromEvent创建的observable很热;元素 产生事件的东西存在于DOM中 - 它不是在创建时创建的 观察者已订阅。
为此您可以使用share运算符,但它仍然无法保证您只能进行一次http调用。共享将multicast
您的可观察对象,使其在订阅者之间共享,但一旦http呼叫完成,它将为新订阅者进行新的http呼叫。
如果您需要缓存行为(执行一次调用,然后在订阅时为每个订阅者提供值),您应该使用publishReplay().refCount()
。
答案 2 :(得分:0)
除了以上答案外,您还可以将http
服务分配给可观察的服务,然后订阅获取数据。例如:
export class App implements OnInit {
cars$: Observable<Car[]>;
constructor(private carsService: carsService) {
}
ngOnInit() {
this.lessons$ = this.lessonsService.loadLessons().publishLast().refCount();
this.lessons$.subscribe(
() => console.log('lessons loaded'),
console.error
);
}
}
答案 3 :(得分:-2)
http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html
调用Observable的执行并注册Observer处理程序 对于它将发出的通知。