在订阅回调函数中取消订阅?

19

我一直在寻找一个简单的方法来避免因为未取消订阅而导致的内存泄漏问题,因为我已经阅读过相关文章。大多数情况下,我只需要从后端接收一次响应。然后我会想要取消订阅。那么为什么不在回调函数中调用它呢?

  onSubmit(){
    var subscription = this.puzzleService.login(this.nameoremail, this.password).subscribe( success =>{
      if(success){
        this.router.navigate(['/puzzles']);
      }
      else{
        this.message="Login failed. Please try again.";
      }
      this.loading=false;
      subscription.unsubscribe();
    });
    this.loading=true;
  }

请注意将订阅分配给本地变量。 然后在闭包内锁定此本地变量并告知在其工作完成时取消订阅。 没有类变量,没有takeUntil,没有其他东西。

它可以编译并且运行时没有错误。 我不熟悉调试器,无法确定可观察对象是否实际上被销毁并随后被垃圾回收。

我错过了什么吗? 有人更熟悉调试器可以纠正我吗? 因为如果这有效,我将在所有地方都这样做。 除了我的pollWords()函数...

这似乎比我看到的其他解决方案简单得多。 我认为我甚至不需要闭包,因为当我在调试器中查看它时,我看到"_this"是"this"的闭包,而"this"实际上是可观察的。 所以,如果有某种方式可以防止发生对"this"的篡改,那么我可以调用"this.unsubscribe()"并完成。 并不是一个可怕的对象引用闭包...

参考资料:

Angular/RxJs何时应该取消订阅`Subscription`

Rxjs可观察生命周期


请查看最近的 GitHub 问题:https://github.com/ReactiveX/rxjs/issues/4318 - cartant
4个回答

25

使用更类似于RxJS的方式来实现你想要的操作,是利用take操作符,像这样:

this.puzzleService.login(this.nameoremail, this.password).pipe(
  take(1)
).subscribe(success => {
  // ...
});

这将使可观察对象发出一个值,然后完成它。

然而,@Picci完全正确,如果您的login方法从HttpClient请求中返回结果,则无需手动取消订阅(也不需要使用take)。


8

取消订阅是为了避免内存泄漏很重要,但如果你"只想从后端得到一个响应",那么取消订阅可能就不是那么重要了。

我的意思是,如果你在this.puzzleService.login后面使用了Angular的http服务,那么你不必担心取消订阅,因为服务本身会在收到响应或发生错误时立即取消订阅。

当你面对通过它们的本质会发出多个值的Observable流时,取消订阅就变得很重要,而这并不是一个http调用的情况,但可能是WebSockets流或其他类型的流的情况。

这篇来自RxJS的顶级贡献者Ben Lesh的文章为这个主题提供了一些启示。


0
我认为一个既能正常工作又是“合法”的结构应该是这样的:

onSubmit() {
    const subscription = this.puzzleService.login(this.nameoremail, this.password)
        .subscribe( success => {
            // your code
            // more of your code
            this.loading = false;
            setTimeout(() => subscription.unsubscribe(), 0);
        });
    this.loading = true;
}

现在.unsubscribe().subscribe(...)中的代码执行后被执行,这意味着订阅已经存在,并且可以取消订阅。

当Observable在同一组件中创建时,.take(1)将起作用,但是如果它不是你自己创建/管理的,例如在另一个组件或服务中创建/管理,则不能仅结束Observable,因为可能还有其他订阅者。然后,您真正想要的只是结束自己的订阅,而不是完全结束Observable。


-1

请把以下与编程有关的内容从英语翻译成中文。只返回翻译后的文本:除非它直接支持您已经放在答案中的内容,否则请不要链接外部内容。 - Enigmativity

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接