调用rxjs的``next``主题`取消http调用
我有一个注销用户的应用程序,我必须打到REST端点。在我的角度2前端,我有以下服务处理此:调用rxjs的``next``主题`取消http调用
@Injectable()
export class AuthService {
private authEvents: Subject<boolean>;
constructor(private http: Http) {
this.authEvents = new Subject<boolean>();
}
login(email: string, password: string): Observable<Response> {
const url = 'rest/auth/login';
const body = {
email: email,
password: password
};
return this.http.post(url, body)
.do((res: Response) => {
localStorage.setItem('currentUser', JSON.stringify(res.json()));
this.authEvents.next(true);
});
}
logout(): Observable<Response> {
const url = 'rest/auth/logout';
return this.http.post(url, {})
.do((res: Response) => {
localStorage.removeItem('currentUser');
console.log('hereee!');
this.authEvents.next(false);
});
}
isSignedIn(): boolean {
return localStorage.getItem('currentUser') !== null;
}
get events(): Observable<boolean> {
return this.authEvents;
}
}
让我解释我在这里要做什么。我有一个authEvents
主题,我订阅我的部件,像这样:
ngOnInit() {
this.isSignedIn = this.authService.isSignedIn();
this.authService.events.subscribe(() => {
this.isSignedIn = this.authService.isSignedIn();
});
}
当用户点击退出按钮,我呼吁这个组件中的以下功能:
logout() {
this.authService.logout()
.subscribe(() => {
this.router.navigate(['/home']);
}, e => this.handleError(e));
}
的问题是,即使注销呼叫尚未完成,浏览器也会重定向到家中。如此有效,有时前端会成功退出,有时却不会!我在这里做错了什么?
注意:自从http调用发生后,后端会话始终退出。我也想看看如何使用Observables(和一般的rxjs)来实现这一点,但如果Promises可以使用太多麻烦的话。
这里是什么工作我:
由于@olsn建议,我将我的Subject
更改为BehaviorSubject
。
但实际上在组件的html中似乎出了问题。
<li routerLinkActive="active"><a href="#" (click)="logout(); $event.preventDefault()">Logout</a></li>
我不得不添加在(click)
事件$event.preventDefault()
电话,一切似乎按预期方式工作。虽然如果有人能向我解释这是为什么,那会很棒!
这是因为'href =“#”' olsn
@olsn它。 –
随着Subject
你有这种情况,排放量只能由用户而不是未来的用户接收。我的猜测是,这是你的问题 - 为了让你的生活更轻松,你可以使用一个BehaviorSubject
,它将当前的价值重新发送给任何未来的用户,所以你不必担心任何赛车 - 条件。
但是:严格看出它不会是一个事件更多,但更多的是状态,这是我会建议你的情况反正用的 - 因为与RxJS您可以利用国家对事件的力量。
@Injectable()
export class AuthService {
public currentUser$: BehaviorSubject<IUser> = new BehaviorSubject(null); // initial state is "null" => user is not logged in
private isSignedIn$: Observable<boolean> = currentUser$.map(user => Boolean(user)).share();
constructor(private http: Http) {
this.authEvents = new Subject<boolean>();
}
login(email: string, password: string): Observable<Response> {
const url = 'rest/auth/login';
const body = {
email: email,
password: password
};
return this.http.post(url, body)
.do((res: Response) => {
localStorage.setItem('currentUser', JSON.stringify(res.json()));
this.currentUser$.next(res.json()); // will automatically trigger the logged-in state as well
});
}
logout(): Observable<Response> {
const url = 'rest/auth/logout';
return this.http.post(url, {})
.do((res: Response) => {
localStorage.removeItem('currentUser');
console.log('hereee!');
this.currentUser$.next(null); // will automatically trigger the logged-in state as well
});
}
}
在你的组件
private desotryed$: Subject<boolean> = new Subject();
ngOnInit() {
this.authService.isSignedIn$
.takeUntil(this.desotryed$) // to prevent memory leaks through a perpetual subscription
.subscribe(isSignedIn => {
this.isSignedIn = isSignedIn;
});
}
ngOnDestroy() {
this.desotryed$.next(true);
}
由于RxJS5文档不包括BehaviorSubject然而,这里是老文档的链接:https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/behaviorsubject.md
这会工作,我相信(谢谢!),但我用另一种方法,我已发布作为答案。添加“$ event.preventDefault()”logout()调用似乎工作。你能告诉我为什么它能工作吗? –
小心使用.do(),因为它主要用于副作用和调试。另外,我会尽可能地避免热门的观察对象。他们可以让您的应用程序调试稍微复杂一些。 – DarkNeuron