在rxjs中,如何使用takeUntil或takeWhile

时间:2018-11-02 16:22:07

标签: angular rxjs

[EDIT 11/5] 在对一些建议的解决方案进行测试之后,我注意到我的某些rxjs导入是错误的(我是从'rxjs / internal'iso从'rxjs'导入的) 。因此,如果您遇到这样的错误,那就可以看看。

关于Stackoverflow的问题已经存在一些与取消订阅可观察项有关的问题,尽管这些问题都不会对我的特定问题有很大帮助。

在我的(“聊天”)应用程序中,我可以通过在搜索框中键入用户的名称来搜索用户。提取用户后,我想显示这些用户是否在线。

这是我的方法。

有一个BehaviorSubject用于捕获搜索词:

private term$ = new BehaviorSubject(null);

只要“可观察的术语”有新的价值,我就会开始寻找新用户:

users$: Observable<User[]> = this.term$.pipe(
    filter(term => !!term),
    switchMap(term => this.usersService.searchUsers(term))
);

但是我也想定期检查这些用户是否“在线”,因此我在Observable上方进行了这样的更改(请注意最后一行):

users$: Observable<any[]> = this.term$.pipe(
    filter(term => !!term),
    switchMap(term => this.usersService.searchUsers(term)),
    switchMap(users => zip(...users.map(user => this.checkLoggedInF(user))))
);

对于所有用户,我创建一个可观察到的“间隔”。 checkedLoggedInF是一项功能,每隔5秒就会与服务器一起检查给定用户是否在线:

checkLoggedInF = user => {
    return interval(5000).pipe(
      switchMap(() => this.usersService.isLoggedIn(user.loginnaam).pipe(
        map(loggedIn => ({...user, loggedIn}))
      ))
    );
}

现在的问题是,每当有一个新的搜索词(在可观察的术语$上)时,都应取消订阅“ checkLoggedIn间隔”可观察的对象。我尝试在“ checkLoggedIn间隔”可观察到和父“ users $”可观察到的情况下都使用takeUntil运算符,但无济于事。同样,使用takeWhile运算符也无效。

2 个答案:

答案 0 :(得分:1)

尝试在调用.tap()的{​​{1}}之前使用switchMap,并将checkLoggedInF中的observable保存在属性中

checkLoggedInF

或您也可以检查并在checkLoggedInF = user => { this.checkLoggedInF$ = interval(5000).pipe( switchMap(() => this.usersService.isLoggedIn(user.loginnaam).pipe( map(loggedIn => ({...user, loggedIn})) )) ); return this.checkLoggedInF$; } users$: Observable<any[]> = this.term$.pipe( filter(term => !!term), switchMap(term => this.usersService.searchUsers(term)), tap(() => { this.checkLoggedInF$ && this.checkLoggedInF$.unsubscribe() }) switchMap(users => zip(...users.map(user => this.checkLoggedInF(user)))) ); unsubscribe()的另一个选项

checkLoggedInF

答案 1 :(得分:0)

最后,这是一个愚蠢的错误,我的某些“ rxjs导入”是错误的(我是从rxjs / internal导入)。修复导入后,switchMap会按预期运行(当“上游”更改时关闭订阅)。

简而言之:不要从'rxjs / internal'导入