Angular 7 错误 RangeError:超出最大调用堆栈大小

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

我试图通过遵循官方教程来学习角度,但是当按照

hero component
hero detail component
的步骤进行操作时,它会引发错误“RangeError:超出最大调用堆栈大小”。

hero.component.html

<ul class="heroes">
  <li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>

<!-- 
<app-hero-detail [hero]="selectedHero"></app-hero-detail> -->


<app-heroes></app-heroes>

detail component

<div *ngIf="hero">

  <h2>{{hero.name}} Details</h2>
  <div><span>id: </span>{{hero.id}}</div>
  <div>
    <label>name:
      <input [(ngModel)]="hero.name" placeholder="name"/>
    </label>
  </div>

</div>

<app-hero-detail [hero]="selectedHero"></app-hero-detail>

hero component

import { Component, OnInit } from '@angular/core';
import { Hero } from '../hero';
import { HEROES } from '../mock-heroes';
import { HeroService } from '../hero.service';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
  heroes: Hero[];

  selectedHero: Hero;

  constructor(private heroService: HeroService) { }

  ngOnInit() {
    this.getHeroes();
  }

  getHeroes(): void {
    this.heroes = this.heroService.getHeroes();
  }

  onSelect(hero: Hero): void {
    this.selectedHero = hero;
  }

}

hero.detail component

import { Component, OnInit, Input } from '@angular/core';
import { Hero } from '../hero';

@Component({
  selector: 'app-hero-detail',
  templateUrl: './hero-detail.component.html',
  styleUrls: ['./hero-detail.component.css']
})
export class HeroDetailComponent implements OnInit {

  @Input() hero: Hero;
  constructor() { }

  ngOnInit() {
  }

}

值得一提的是,当

<app-heroes></app-heroes>
被评论时,列表页面加载没有错误

Error message screenshot 感谢任何帮助

angular angular7
14个回答
46
投票

1.出现死循环时会出现此错误。 正如您所提到的,当 app-heroes 被注释时,页面会加载,这可能会被用作多个组件的选择器名称,这是不允许的。 这可能会导致无限循环并无法加载组件。

  1. 尝试进行以下编辑,

hero.component.html

<ul class="heroes">
  <li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>

<app-hero-detail [hero]="selectedhero"></app-hero-detail> 

hero.detail.component.html

<div *ngIf="hero">
  <h2>{{hero.name}} Details</h2>
  <div><span>id: </span>{{hero.id}}</div>
  <div>
    <label>name:
      <input [(ngModel)]="hero.name" placeholder="name"/>
    </label>
  </div>
</div>

希望这有帮助。


8
投票

当我在 Angular 9 上错误地使用循环模块导入时,发生了此错误。

import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
@NgModule({
 imports: [
    CommonModule,
    ModuleTwo
  ],
 
})
export class ModuleOne {
}

import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
    @NgModule({
    imports: [
        CommonModule,
        ModuleOne
      ],
     
    })
    export class ModuleTwo {
    }

7
投票

在您的示例中,您在自己内部渲染组件,因此您永远不会完成此操作,并且始终渲染另一个子组件(如果块的第二部分是

更新 - 更多详细信息:

如果您使用组件编写应用程序,则所有组件都是分层的,因此只有当您确定这是有限数量的循环时,您才可以在自己内部包含相同的组件。在您的代码示例中,您有无限的嵌套组件,因为子组件会在您的体内生成下一个子组件。结果您的浏览器显示错误:

RangeError: Maximum call stack size exceeded

hero.component.html

<ul class="heroes">
  <li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>

<!-- 
<app-hero-detail [hero]="selectedHero"></app-hero-detail> -->


<app-heroes></app-heroes>

app-hero-details.component.html

<div *ngIf="hero">

  <h2>{{hero.name}} Details</h2>
  <div><span>id: </span>{{hero.id}}</div>
  <div>
    <label>name:
      <input [(ngModel)]="hero.name" placeholder="name"/>
    </label>
  </div>

</div>

// you should comment line below
// <app-hero-detail [hero]="selectedHero"></app-hero-detail>

7
投票

我将添加一个答案,描述将现有应用程序升级到 Angular 8 并使用新的路由功能时导致此错误的不同原因。

在我的例子中,我使用新语法将

data
对象添加到每个延迟加载的路线中,并将
preload
设置为
true || false

  {
    path: '',
    loadChildren: () => import('./views/home/home.module').then(mod => mod.HomeModule),
    data: { preload: true }
  },

但是我花了一段时间才意识到我在

preloadingStrategy
forRoot 声明中将
PreloadAllModules
设置为
RouterModule

@NgModule({
  imports: [RouterModule.forRoot(
    routes,
    {
      preloadingStrategy: PreloadAllModules, <-- This is the cause
    })],
    ...

从模块 forRoot 声明中删除 preloadingStrategy 并依赖路由数据预加载定义修复了该问题。


6
投票

当我的智能感知意外地将模块名称(而不是特定组件名称)添加到模块的导出时,我正在处理此错误:

@NgModule({
  declarations: [
    FooComponent,
    // ...
  ],
  imports: [CommonModule],
  exports: [
    FooModule, // <== should be 'FooComponent'
    // ...
  ], 
})
export class FooModule {}

如果错误能更具描述性的话,那就太好了,因为这个工具我有时会用到


4
投票

您可以在详细信息 HTML 中显示

<app-hero-detail>

<app-hero-detail [hero]="selectedHero"></app-hero-detail>

请尝试删除它。

hero.component.html
中注释了类似的行,您可以取消注释。


2
投票

将现有应用程序升级到 Angular 8 并在单独的文件中使用新的路由功能时,导致此错误的另一个原因。

在我的情况下,不将

featureRouterModule
导入到其特定的
featureModule.ts
会导致最大堆栈超出错误。因为 Angular 无法找到其注册的特定路由器文件


2
投票

当我创建模块但忘记添加 RoutingModule 时,我能够重现此错误消息。

@NgModule({
  declarations: [
  SuccessComponent,
  CheckoutComponent
],
  imports: [
    ShareModule,
    PaymentRoutingModule // Forget to add it.
  ]
})
export class PaymentModule { }

我不知道为什么会出现这个错误,但也许其他人也会犯同样的错误。


2
投票

我发现的此错误的可能情况:

  • 2 个或更多同名模块
  • 您的
    app.module.ts
    文件中导入错误
  • 编译问题

您可以尝试的解决方案:

  • 对于第 1 点,更改名称并使其独一无二
  • 对于第 2 点,确保所有导入都是按照您的模块用例进行的,请检查模块之间的相互依赖关系
  • 对于第 3 点,这种情况很少见,但如果浏览器没有足够的内存来处理,就会发生这种情况,因此请尝试重新启动代码编辑器、浏览器或 PC。

1
投票

当我订阅可观察对象的频率超过要求时,就会发生这种情况。我在每次按下 Enter 键时都会订阅以下可观察到的内容,

this.filteredOptions.subscribe((res) => this.addSelectedContacts(event, res[keyManager.activeItemIndex]))

这显然不是必需的,我必须通过添加管道(take(1))来限制可观察到仅获得第一次发射,

this.filteredOptions.pipe(take(1)).subscribe((res) => this.addSelectedContacts(event, res[keyManager.activeItemIndex]))

您还可以使用 swithMap 运算符语法来取消以前的订阅。


0
投票

我对两个模块进行了类似的命名,但没有注意导入的是哪个。 如果您在其内部导入模块,则会导致循环导入,直到达到最大调用堆栈。


0
投票

我解决了在从同一服务中执行的服务中删除调用后遇到的无限循环问题,但行为不同。


0
投票

就我而言,我错误地将一些组件放入模块的导入数组中,而不是将它们放入导出数组中。


-1
投票

角度12

我在无限循环中遇到这个问题,这会导致 ui 在每次迭代时发生变化。

© www.soinside.com 2019 - 2024. All rights reserved.