Angular - 从内存中删除对象而不破坏组件

问题描述 投票:0回答:1

我有一个非常复杂的角度应用程序,它会导致浏览器很快崩溃。所以我正在寻求优化它。我修复了每个订阅内存泄漏,但问题仍然存在。所以我使用Chrome调试模块来尝试找出问题所在。在“内存”选项卡中,我进行记录会话以查找出了什么问题。首先我只激活一些需要理解的东西。

我有一个永远不会破坏的组件,每次点击菜单都会调用refreshWrapper()函数:

refreshWrapper() {
    // RESET
    this.appS.structure.reset(this.type, this.wrapper, this.appS.navigationS.navigations[this.type + '.' + this.wrapper].step);
    // GET GRID
    this.appS.restS.post('grid/elements', { route: this.route }).subscribe(response => {
            this.appS.structure.displayeds[this.type + '.' + this.wrapper] = new SiteModule(response.displayed);
    });
}

这是我的结构模型重置函数,我尝试清除变量:

reset(type: string, wrapper: string, step: string) {
     delete this.displayeds[type + '.' + wrapper];
}

查看我的 SiteModule 类构造函数:

constructor(datas ?) {
Object.assign(this, datas);
// GRIDS
if (datas?.grids) {
  this.grids = [];
  datas.grids.forEach(grid => {
    this.grids.push(new Grid(grid));
  });
}

}

在网格类中

constructor(datas ?, element ?: Element) {
Object.assign(this, datas);
// BLOCS
if (datas?.blocs) {
  this.blocs = [];
  datas.blocs.forEach(bloc => {
    this.blocs.push(new GridBloc(bloc, element));
  });
}

}

GridBloc 类

constructor(datas ?, element ?: Element) {
Object.assign(this, datas);
// ELEMENTS
if (datas?.elements) {
  this.elements = [];
  datas.elements.forEach(e => {
    this.elements.push(new Element(e, element));
  });
}

}

元素类

constructor(datas ?, element ?: Element) {
Object.assign(this, datas);
// DETAILS
if (datas?.details) {
  this.details = [];
  datas.details.forEach(detail => {
    this.details.push(new Detail(detail, this.ressource_id));
  });
}

}

在 Chrome 内存选项卡中,我看到只有一个 SiteModule 对象。但它保留链接的对象,即我有很多元素对象(即使当我单击菜单时,它也会保留旧的对象,因此当调用refreshWrapper函数时)。

这里有一个内存选项卡屏幕,显示 Element Class(第一个引用 element.model.ts:61 的是好的),但所有其他都是旧的。旧的“[10] dans (GC root) @3”是什么意思?

我不明白为什么。我认为这是垃圾收集器问题,因为我没有销毁组件,并且我将变量存储在全局服务(此处为 AppS)中,但如何解决这个问题?有什么想法吗?

angular memory-leaks garbage-collection components
1个回答
0
投票

我修复了每个订阅内存泄漏,但问题仍然存在。

在给定的代码中已经存在可见的内存泄漏。

// GET GRID
this.appS.restS.post('grid/elements', { route: this.route })
  .subscribe(response => {
    this.appS.structure.displayeds[this.type + '.' + this.wrapper] = new SiteModule(response.displayed);
  });

这是一次订阅,无法取消订阅。我不知道您的

refreshWrapper
函数被调用的频率,但每次调用都会在您的内存中添加一个订阅。

作为解决方案,我建议使用管道

first
take(1)
运算符。

// GET GRID
this.appS.restS.post('grid/elements', { route: this.route })
  .pipe(
    first(),
  ).subscribe(response => {
    this.appS.structure.displayeds[this.type + '.' + this.wrapper] = new SiteModule(response.displayed);
  });
© www.soinside.com 2019 - 2024. All rights reserved.