gpt4 book ai didi

angular - 如何避免 Angular 9 中复杂 RxJS 管道的内存泄漏?

转载 作者:行者123 更新时间:2023-12-04 01:24:37 24 4
gpt4 key购买 nike

我的 Angular + RxJS 应用程序中有这个有点复杂的管道结构:

远程数据.service.ts:

getAll(url): Observable<any[]> {
return this.http.get(url, this.options)
.pipe(map((result: any[]) => result));
}

proxy.service.ts:

// localDataService use my LocalDataService
// remoteDataService use my RemoteDataService

getAll(model): Observable<any[]> {
if (model.use_localstorage) {
return this.localDataService.getAll(model)
.pipe(map((result: any[]) => result));
} else {
return this.remoteDataService.getAll(model.url)
.pipe(map((result: any[]) => result));
}
}

helper.service.ts:

getAll(model): Observable<any[]> {
// do some general fancy things...
return this.proxyService.getAll(model)
.pipe(map((result: any) => result));
}
}

然后在我的 组件 :

export class MyComponent {
helperService = new HelperService();
model = new MyModel();

getAll() {
this.helperService.getAll().subscribe((result: any[]) => {
// parse result
});
}
}

如您所见,我从远程数据服务、代理服务、辅助服务和组件构建了一个管道。当然原因是将每个功能彼此分开,使我的服务更可重用。

我的目标是避免内存泄漏。

问题是:如果我想放一个 take(1) RxJS 操作符进入我的管道就足以将它放入管道的末尾,在 .subscribe() 之前或者也需要把它放在每个服务和组件中?

在这种情况下,避免内存泄漏的最佳做法是什么?

最佳答案

这取决于。 pipe(take(1))确保你得到一个“单值可观察”的意思,它会发出一个值然后完成,并关闭订阅,因此没有内存泄漏。
如果您的服务或函数本身仅发出单个值 pipe(take(1))什么也没做。

例如,如果您有一个 REST 调用,使用 httpclient.get(...)它可能有延迟。那么你应该使用 pipe(timeout(3000))pipe(takeUntil(...))确保没有订阅活着,如果您的组件或任何东西被破坏,您就没有内存泄漏或订阅内部逻辑的意外行为。即使与 pipe(take(1))内存泄漏可能存在,因为它仅在发出一个值或错误后才会完成。

因此,如果您有 http.get()它有网络延迟。并且你会使用“pipe(take(1))”它仍然会导致内存泄漏,因为它只等待一个值,并且当值到达时订阅将被触发,即使你调用的组件是销毁或您已导航到应用程序的其他 View 。

takeUntil(...) 对组件很有用,如果它们被销毁,你可以触发订阅结束 ngDestroy() .

  public isActive = new Subject();

public ngOnDestroy(): void {
this.isActive.next(false);
}

public fun():void{
this.fooService.getValue()
.pipe(takeUntil(this.isActive))
.subscribe( value => console.log(value));
}

如果 Observable/Subject 完成,则在发出最后一个值后应该没有内存泄漏。

您需要处理这些情况,如果您不确定,有一个“complete()”或者它只发出 One 值但延迟可能有问题。

顺便说一下,内存泄漏是次要问题,甚至没有那么大。更成问题的是,当您不想再订阅时,您的订阅逻辑可能会被触发。
有时您想触发订阅中的逻辑(例如,通知用户某事已成功),即使用户已经离开 View 。
所以这取决于。

您也可以将所有订阅存储在单个订阅中,如果您想处理它们,请取消订阅。
  public subs = new Subscription();

public ngOnDestroy(): void {
this.subs.unsubscribe();
}

public fun():void{
const bar: Subscription = this.fooService.getValue()
.subscribe( value => console.log(value));
this.subs.add(bar);
}

关于angular - 如何避免 Angular 9 中复杂 RxJS 管道的内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62114244/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com