提问者:小点点

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


我一直在寻找一种简单的方法来避免我读过的因未能取消订阅而导致的内存泄漏。大多数时候,我只是想要后端的ONE响应。然后我会想要取消订阅。那么为什么不在回调中调用它呢?

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

请注意将订阅分配给局部变量。然后,该局部变量被锁定在闭包中,并在其工作完成时被告知取消订阅。没有类变量,没有取值,没有其他。

它编译和运行没有错误。我对调试器不够熟悉,无法确定可观察对象是否真的被销毁并随后被垃圾回收。

我遗漏了什么吗?更熟悉调试器的人可以纠正我吗?因为如果这有效,我将在任何地方都这样做。除了在我的polWords()函数中…

这似乎比我看到的其他解决方案要简单得多。我认为我甚至不需要闭包,因为当我在调试器中查看它时,我看到“_this”是“this”的闭包,而“this”实际上是可观察的。因此,如果有某种方法可以防止“this”发生的改变,那么我可以调用“this.取消订阅()”并完成。并不是说对象引用闭包是一件可怕的事情…

参考资料:

Angular/RxJs我什么时候应该取消订阅

Rxjs可观察生命周期


共3个答案

匿名用户

一种更像RxJS的方式来做你想做的事情是使用采取运算符,如下所示:

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

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

但是,@Picci是完全正确的,如果您的login方法从HttpClient请求返回结果,您不需要手动取消订阅(也不需要使用采取,就此而言)。

匿名用户

取消订阅对于避免内存泄漏很重要,但如果您“只想从后端获得一个响应”,它可能并不那么重要。

我的意思是,如果在您的this. decleService.login后面您正在使用Angular超文本传输协议服务,那么您不必担心取消订阅,因为服务本身一旦从后端获得响应就会取消订阅,或者发生错误。

当您面对本质上发出多个值的可观察流时,取消订阅非常重要,这不是超文本传输协议调用的情况,而是网络套接字流或其他类型流的情况。

本·莱什的这篇文章,如果不是RxJS的负责人,也是最大的贡献者,为这个话题提供了一些启示。

匿名用户

一个应该工作的建筑,也是“合法的”,我认为是这样的:

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

现在. un订阅()是在中的代码之后执行的。订阅(…),这意味着订阅存在,并且可以取消订阅。

当在同一个组件中创建可观察对象时,. get(1)将起作用,我认为如果它不是你的,你不能仅仅结束可观察对象,例如,当由另一个组件或服务创建/管理时,因为可能还有其他订阅者。那么你真的只想结束自己的订阅,而不是完成可观察对象。