为什么Angular元素会吞噬错误?

mcvgt66p  于 6个月前  发布在  Angular
关注(0)|答案(7)|浏览(81)

在Angular项目中,我有一个最简单的Angular元素。我在属于Angular元素的组件中抛出错误,如下所示:
dashboard-tile.component.ts: (index.html 中引用为 <dashboard-tile a="100" b="50" c="25"></dashboard-tile>)

ngOnInit() {
    debugger;
    throw "this is an error";
  }

但是在Chrome控制台中看不到错误。链接到 video
然而,如果我开始将此组件用作普通组件,我立即会在控制台中看到错误。所以这可能是一个angular-element问题。链接到包含代码的github repo
已在Chrome和Firefox上测试,可重现,所以这不是浏览器问题。
其他信息:
Angular CLI: 7.1.4
Node: 10.14.2
操作系统:win32 x64
Angular: 7.1.4
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router

包版本

@angular-devkit/architect 0.11.4
@angular-devkit/build-angular 0.11.4
@angular-devkit/build-optimizer 0.11.4
@angular-devkit/build-webpack 0.11.4
@angular-devkit/core 7.1.4
@angular-devkit/schematics 7.1.4
@angular/elements 7.2.8
@ngtools/webpack 7.1.4
@schematics/angular 7.1.4
@schematics/update 0.11.4
rxjs 6.3.3
typescript 3.1.6
webpack 4.23.1

eivnm1vs

eivnm1vs1#

PR 38090 包含此文档问题的修复。

00jrzges

00jrzges2#

@gkalpak:据我所知,我们需要记录这样一个事实:“在根模块的构造函数中抛出的任何错误都会被吞掉。”(来自评论。)这是否应该在bootstrapping.md中显示一个简单的警告?谢谢。

1hdlvixo

1hdlvixo3#

SGTM, @rockument69。

mjqavswn

mjqavswn4#

这让我抓狂。在ngDoBootstrap内部定义元素解决了这个问题,错误日志再次出现。

kmbjn2e3

kmbjn2e35#

这仍然似乎是v9中的一个问题:Updated StackBlitz
@alexzuza是正确的:这是因为在示例化模块时,将错误转发到ErrorHandler的ngZone.onError订阅尚未创建。必须这样做,因为我们需要在订阅ngZone.onError之前获取模块示例的ErrorHandler
顺便说一下,这并不仅限于@angular/elements。任何在根模块构造函数中抛出的错误都会被吞掉。
我们应该记录这一点(添加comp: docs标签)。
此外,我们还可以订阅ngZone.onError并在示例化根模块时仅捕获任何错误(但这可能是一个破坏性的变化)。
最后,显而易见的解决方法是将代码推迟到模块示例化之后执行。有很多方法可以实现这一点,例如(不按顺序排列):

  • 确保代码异步运行 - 例如通过将代码 Package 在setTimeout()Promise.resolve().then()中:
expost class AppModule {
  constructor() {
    setTimeout(() => /* Error-throwing code. */);
  }
}
  • 将代码从AppModule#constructor()移动到AppComponent#constructor()。(顺便说一下,这是我们在Angular Element guide实时演示中展示的内容。)
export class AppModule {
  constructor() { /* Nothing here. */ }
}

export class AppComponent  {
  constructor() { /* Error-throwing code. */ }
}
@NgModule({
  ...
  providers: [
    {
      provide: APP_BOOTSTRAP_LISTENER,
      useFactory: (...injectedDeps) =>
        () => /* Error-throwing code. */,
      deps: [/* Deps... */],
      multi: true,
    },
  ],
})
export class AppModule {
  constructor() { /* Nothing here. */ }
}
  • 将代码移动到模块的ngDoBootstrap()方法。由于ngDoBootstrap()不能与@NgModule > bootstrap一起使用,因此还必须将 Bootstrap 或AppComponent移动到ngDoBootstrap():
@NgModule({
  ...
  bootstrap: [ /* Nothing here. */ ],
})
export class AppModule implements DoBootstrap {
  constructor() { /* Nothing here. */ }

  ngDoBootstrap(appRef: ApplicationRef): void {
    // "Manually" bootstrap `AppComponent`.
    appRef.bootstrap(AppComponent);

    /* Error-throwing code. */
  }
}
1tuwyuhd

1tuwyuhd6#

我猜在ngZone.onError中还没有订阅自定义元素的定义,你可以尝试将代码移动到ngDoBootstrap方法中,这样你就能看到错误了。

pwuypxnk

pwuypxnk7#

@alexzuza 我不想实现自己的 ngDoBootstrap ,因为我想在更大的 Angular 项目中使用我的元素,而不必为生产构建它。正如您在我的 index.html

<app-root></app-root>
 <dashboard-tile a="100" b="50" c="25"></dashboard-tile>

中所看到的。

相关问题