Angular 5自定义ErrorHandler调用Material Snackbar遇循环依赖求助
解决Angular 5中ErrorHandler调用MatSnackBar的循环依赖问题
问题描述
我在Angular 5应用中尝试使用Material Snackbar展示后端错误,但多次尝试均未成功,似乎ErrorHandler类需要特定方式才能正确调用Snackbar。目前我遇到如下错误:
Provider parse errors: Cannot instantiate cyclic dependency! ApplicationRef ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1 Evaluating main.ts
我的自定义ErrorHandler类(不含导入语句)如下:
@Injectable() export class MyErrorHandler implements ErrorHandler { constructor(public snackBar: MatSnackBar) {} handleError(error) { const errorMsg = 'an error has happened'; this.openSnackBar(errorMsg); } openSnackBar(message: string) { this.snackBar.open(message); } }
试过很多现有问题的解决方案,但都没法匹配我的场景,求解决建议。
解决方案
这个问题的根源是循环依赖:Angular在应用初始化早期就会加载ErrorHandler,而MatSnackBar依赖ApplicationRef,ApplicationRef又依赖ErrorHandler,直接在构造函数中注入MatSnackBar会导致注入器陷入闭环。
这里给你一个亲测有效的解决方法,通过Injector延迟获取MatSnackBar实例:
1. 修改自定义ErrorHandler类
将构造函数中的MatSnackBar替换为Injector,在需要使用Snackbar时再动态获取实例:
import { ErrorHandler, Injectable, Injector } from '@angular/core'; import { MatSnackBar } from '@angular/material'; @Injectable() export class MyErrorHandler implements ErrorHandler { private snackBar: MatSnackBar; constructor(private injector: Injector) {} handleError(error) { // 延迟获取实例,避开初始化阶段的循环依赖 if (!this.snackBar) { this.snackBar = this.injector.get(MatSnackBar); } const errorMsg = 'an error has happened'; this.openSnackBar(errorMsg); } openSnackBar(message: string) { // 可以添加关闭按钮和持续时间优化体验 this.snackBar.open(message, 'Close', { duration: 3000, }); } }
2. 确保根模块正确注册ErrorHandler
在AppModule中替换默认的ErrorHandler为自定义类,同时别忘了导入Snackbar模块:
import { NgModule, ErrorHandler } from '@angular/core'; import { MyErrorHandler } from './path-to-your-handler'; import { MatSnackBarModule } from '@angular/material/snack-bar'; @NgModule({ imports: [ // ...其他业务模块 MatSnackBarModule ], providers: [ { provide: ErrorHandler, useClass: MyErrorHandler } ], // ...其他配置 }) export class AppModule { }
这样修改后,MatSnackBar的实例只会在第一次捕获错误时被创建,完美避开了初始化时的循环依赖问题。
内容的提问来源于stack exchange,提问作者Ahmed Elkoussy
相关产品推荐
相关产品推荐

