首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >尽管在BehaviorSubject中清除了内存,但ngOnDestroy还是会产生内存泄漏

尽管在BehaviorSubject中清除了内存,但ngOnDestroy还是会产生内存泄漏
EN

Stack Overflow用户
提问于 2020-05-22 14:59:55
回答 2查看 1.1K关注 0票数 1

我有一个地址组件,是通过*ngIf切换的.此地址组件包含一个mat-autocomplete (摘录):

address-component.html

代码语言:javascript
运行
复制
<mat-form-field class="full-width" appearance="outline">
  <mat-label>Straße</mat-label>
  <input matInput [matAutocomplete]="auto" type="text" [formControlName]="formControlMapping.street" />
  <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
    <mat-option *ngFor="let street of streets$ | async" [value]="street">
      {{ street }}
    </mat-option>
  </mat-autocomplete>
</mat-form-field>

mat-autocomplete的不同选项是从BehaviorSubject派生的。为了防止内存泄漏,我在completeunsubscribe中使用ngOnDestroy。尽管如此,我还是设法产生了内存泄漏,因为在通过*ngIf切换组件并试图将新值写入BehaviorSubject后,我得到了以下错误。

代码语言:javascript
运行
复制
ObjectUnsubscribedErrorImpl {message: "object unsubscribed", name: "ObjectUnsubscribedError"}

我做错了什么?我在哪里产生内存泄漏?

address-component.ts

代码语言:javascript
运行
复制
export class AddressFormComponent implements OnInit, OnDestroy {
  @Input() formGroup: FormGroup;
  public streetSubject = new BehaviorSubject<string[]>([]);
  public streets$: Observable<string[]>;

  ngOnInit(): void {
    ...
    this.formGroup.get(this.formControlMapping.zipCode).valueChanges.subscribe({
      next: () => {
        this.addressService
          .getStreets()
          .pipe(
            tap((streets) => {
              this.streetSubject.next(streets);
              this.streets$ = of(this.filter(this.formGroup.get(this.formControlMapping.street).value, streets));
            })
          )
          .subscribe();
      }
    });
    ...
    this.disableDependingForms();
  }

  disableDependingForms(): void {
    ...
    this.addressService.getStreets().subscribe({
      next: (val) => {
        const street = this.formGroup.get(this.formControlMapping.street).value;
        this.streetSubject.next(val);
        this.streets$ = this.streetSubject.pipe(map((streets) => this.filter(street, streets)));
      }
    });
    ...
  }

  ngOnDestroy(): void {
    this.streetSubject.complete();
    this.streetSubject.unsubscribe();
  }
}

编辑:

我的目标是:根据zipCode的值,我需要从api中获取位于zipCode区域的街道。有几个其他条件必须满足,才能找到街道,但这些条件是静止的,不会使任何事情复杂化。当zipCode值发生变化时,街道将被更新。基本上:根据名为formControl zipCode.的值从API获取街道

泄漏的原因是调用this.streetSubject.next(streets); The next

我试过了,但ObjectUnsubscribedErrorImpl仍然存在。有什么建议吗?

代码语言:javascript
运行
复制
this.formGroup
  .get(this.formControlMapping.zipCode)
  .valueChanges.pipe(
    switchMap((zipCode: string) => {
      return this.addressService.getStreets().pipe(
        map((val) => ({ streets: val, zipCode })),
        takeUntil(this.unsubscribe)
      );
    }),
    takeUntil(this.unsubscribe)
  )
  .subscribe({
    next: ({ zipCode, streets }) => {
      ...
      this.streetSubject.next(streets);
      ...
    }
  });
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-05-26 10:53:34

当然,通过takeUntil取消订阅的正确方法是:

代码语言:javascript
运行
复制
  ngOnDestroy(): void {
    this.unsubscribe.next();
    this.streetSubject.complete();
  }

不是:

代码语言:javascript
运行
复制
  ngOnDestroy(): void {
    this.streetSubject.complete();
    this.streetSubject.unsubscribe();
  }

使用正确的方法进行unsubscribe,一切都很好。

票数 0
EN

Stack Overflow用户

发布于 2020-05-22 15:02:57

你从来不取消订阅这些

代码语言:javascript
运行
复制
this.formGroup.get(this.formControlMapping.zipCode).valueChanges.subscribe(

如果getStreets不是web请求,它也可能是泄漏的。

代码语言:javascript
运行
复制
this.addressService.getStreets().subscribe({
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61957895

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档