调用rxjs的``next``主题`取消http调用

调用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可以使用太多麻烦的话。

+0

小心使用.do(),因为它主要用于副作用和调试。另外,我会尽可能地避免热门的观察对象。他们可以让您的应用程序调试稍微复杂一些。 – DarkNeuron

这里是什么工作我:

由于@olsn建议,我将我的Subject更改为BehaviorSubject

但实际上在组件的html中似乎出了问题。

<li routerLinkActive="active"><a href="#" (click)="logout(); $event.preventDefault()">Logout</a></li> 

我不得不添加(click)事件$event.preventDefault()电话,一切似乎按预期方式工作。虽然如果有人能向我解释这是为什么,那会很棒!

+2

这是因为'href =“#”' olsn

+0

@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

+0

这会工作,我相信(谢谢!),但我用另一种方法,我已发布作为答案。添加“$ event.preventDefault()”logout()调用似乎工作。你能告诉我为什么它能工作吗? –