经过一段时间的测试、阅读文档和HttpClient源代码。
HttpClient:
https://github.com/angular/angular/blob/master/packages/common/http/src/client.ts
HttpXhrBackend :
https://github.com/angular/angular/blob/master/packages/common/http/src/xhr.ts
HttpClientModule
:https://indepth.dev/exploring-the-httpclientmodule-in-angular/
Angular University:https://blog.angular-university.io/angular-http/
这种类型的Observables是单值流:如果HTTP请求成功,这些Observables将仅发出一个值,然后完成
而整个“我需要”取消订阅的问题的答案取决于你的回调函数中的逻辑。
这要看情况。
Http调用内存泄漏不是一个问题。
问题在于回调函数中的逻辑。
例如:路由或登录。
如果您的调用是一个登录调用,则不需要“取消订阅”,但您需要确保如果用户离开页面,则在缺乏用户时正确处理响应。
this.authorisationService
.authorize(data.username, data.password)
.subscribe((res: HttpResponse<object>) => {
this.handleLoginResponse(res);
},
(error: HttpErrorResponse) => {
this.messageService.error('Authentication failed');
},
() => {
this.messageService.info('Login has completed');
})
从烦人到危险
现在想象一下,网络比平常慢,通话需要长达5秒钟,用户离开登录视图并进入“支持视图”。
组件可能没有激活,但订阅仍在进行中。如果有响应,用户将会突然重定向(取决于您的handleResponse()实现)。
这是不好的。
还要想象一下,用户离开电脑,认为他还没有登录。但是您的逻辑已经将用户登录,现在您面临安全问题。
在不取消订阅的情况下,您可以做什么?
使您的调用依赖于视图的当前状态:
public isActive = false;
public ngOnInit(): void {
this.isActive = true;
}
public ngOnDestroy(): void {
this.isActive = false;
}
使用.pipe(takeWhile(value => this.isActive))
,以确保只有在视图处于活动状态时才处理响应。
this.authorisationService
.authorize(data.username, data.password).pipe(takeWhile(value => this.isActive))
.subscribe((res: HttpResponse<object>) => {
this.handleLoginResponse(res);
},
(error: HttpErrorResponse) => {
this.messageService.error('Authentication failed');
},
() => {
this.messageService.info('Login has completed');
})
但是你如何确定订阅不会导致内存泄漏?
您可以记录是否应用了“teardownLogic”。
当订阅为空或取消订阅时,将调用订阅的teardownLogic。
this.authorisationService
.authorize(data.username, data.password).pipe(takeWhile(value => this.isActive))
.subscribe((res: HttpResponse<object>) => {
this.handleLoginResponse(res);
},
(error: HttpErrorResponse) => {
this.messageService.error('Authentication failed');
},
() => {
this.messageService.info('Login has completed');
}).add(() => {
this.messageService.info('Teardown');
});
你不必取消订阅。你应该知道,如果你的逻辑存在问题,这可能会导致订阅出现问题。并对其进行处理。在大多数情况下,这不是问题,但特别是在关键任务(如授权)中,您应该注意意外行为,无论是使用“取消订阅”还是其他逻辑(如管道或条件回调函数)。
为什么不总是取消订阅?
想象一下,您发出了一个put或post请求。服务器都会接收到消息,只是响应需要一段时间。取消订阅不会撤销put或post请求。
但是,当您取消订阅时,您将没有机会处理响应或通知用户,例如通过对话框或Toast / Message等。这会导致用户认为put / post请求未完成。
所以这取决于你。这是你的设计决策,如何处理这些问题。