简体   繁体   English

在 rxjs 中,如何使用 takeUntil 或 takeWhile 取消订阅“内部”“间隔”可观察量

[英]In rxjs, how to unsubscribe from "inner" "interval" observables using takeUntil or takeWhile

[EDIT 11/5] After testing with some of the suggested solutions, I noticed some of my rxjs imports were wrong (I was importing from 'rxjs/internal' iso from 'rxjs'). [编辑 11/5]在使用一些建议的解决方案进行测试后,我注意到我的一些 rxjs 导入是错误的(我是从 'rxjs' 中的 'rxjs/internal' iso 导入的)。 So if you come across an error like this, that's something that you might have a look at.因此,如果您遇到这样的错误,您可能需要查看一下。

There already exist a couple of questions on Stackoverflow related to unsubscribing from an observable, though none of them are very helpful to my specific problem. Stackoverflow 上已经存在一些与取消订阅可观察对象相关的问题,尽管它们都对我的具体问题没有帮助。

In my ("chat") application, I can search for users by typing their name in a search box.在我的(“聊天”)应用程序中,我可以通过在搜索框中键入用户的姓名来搜索用户。 After fetching the users, I want to display whether these users are online or not.获取用户后,我想显示这些用户是否在线。

Here's my approach.这是我的方法。

There's a BehaviorSubject for capturing the search term:有一个 BehaviorSubject 用于捕获搜索词:

private term$ = new BehaviorSubject(null);

Whenever there's a new value on the term$ observable, I start looking for new users:每当 term$ observable 有新值时,我就会开始寻找新用户:

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

But I also want to periodically check whether these users are "online", hence I change above Observable like so (note that last line):但我也想定期检查这些用户是否“在线”,因此我像这样更改了 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))))
);

For all users I create an "Interval" observable.对于所有用户,我创建了一个“间隔”可观察对象。 checkedLoggedInF is a function that checks every 5 seconds with the server whether the given user is online: checkedLoggedInF 是一个函数,它每 5 秒检查一次给定用户是否在线:

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

Now the problem is that whenever there is a new search term (on the term$ observable), the "checkLoggedIn interval" observables should be unsubscribed to.现在的问题是,只要有新的搜索词(在 term$ observable 上),就应该取消订阅“checkLoggedIn 间隔”observable。 I have tried using a takeUntil operator in both the "checkLoggedIn interval" observable and the parent "users$" observable, but to no avail.我尝试在“checkLoggedIn 间隔”可观察和父“users$”可观察中使用 takeUntil 运算符,但无济于事。 Also using a takeWhile operator was ineffective.使用 takeWhile 操作符也是无效的。

try to use .tap() before switchMap where you are calling checkLoggedInF , and save your observable from checkLoggedInF in a property尝试使用.tap()之前switchMap你在哪里打电话checkLoggedInF ,并保存您observablecheckLoggedInF在属性

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))))
);

or another option you can check and unsubscribe() in your checkLoggedInF too或者您也可以在checkLoggedInF检查和unsubscribe()其他选项

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

In the end it was a stupid mistake on my side, some of my 'rxjs imports' were wrong (I was importing from rxjs/internal).最后,这对我来说是一个愚蠢的错误,我的一些“rxjs 导入”是错误的(我是从 rxjs/internal 导入的)。 When I fixed the imports, switchMap functions as expected (closing the subscription when the "upper stream" changes).当我修复导入时,switchMap 按预期运行(当“上游”更改时关闭订阅)。

So in short: don't import from 'rxjs/internal'简而言之:不要从 'rxjs/internal' 导入

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM