我一直在寻找一种简单的方法来避免由于未取消订阅而导致的我所读到的内存泄漏。大多数时候,我只希望后端提供一个响应。然后,我想退订。那么为什么不在回调中调用它呢?
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()”并完成操作。并不是说对象引用关闭是一件可怕的事情……
参考文献:
答案 0 :(得分:5)
一种更类似于RxJS的操作方式是使用take
运算符,如下所示:
this.puzzleService.login(this.nameoremail, this.password).pipe(
take(1)
).subscribe(success => {
// ...
});
这将使可观察对象恰好发出一个值,然后完成该值。
但是,@ Picci是完全正确的,如果您的login
方法返回了HttpClient
请求的结果,则无需手动退订(也不必使用take
问题)。
答案 1 :(得分:4)
取消订阅对于避免内存泄漏很重要,但是如果您“只是想从后端获得一个响应”,那么取消订阅就不那么重要了。
我的意思是,如果在您的this.puzzleService.login
后面使用的是Angular http
服务,那么您不必担心取消订阅,因为服务本身会在收到响应后立即取消订阅从后端开始,否则发生错误。
当您遇到可观察到的流时,取消订阅很重要,该流本质上会发出多个值,这不是http调用的情况,而是Web套接字流或其他类型的流的情况。 / p>
这位article from Ben Lesh是RxJS的主要贡献者,即使不是RxJS的负责人,也为该话题提供了一些启示。
答案 2 :(得分: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。
答案 3 :(得分:-1)
这是一个非常棘手的问题-我有时也取消订阅局部变量,但我认为这种方式并不像看起来那样合适。 您可以在以下反应式Fox文章中阅读有关所有极端情况的信息(保存对此的引用,将其保存为组件变量等):https://medium.com/angular-in-depth/why-you-have-to-unsubscribe-from-observable-92502d5639d0