Angular全局ErrorHandler触发多次Material Snackbar重叠问题求解
解决方案
一、限制snackbar仅展示1次
你可以利用MessageNotificationService是根级别单例的特性,添加状态控制避免重叠弹出,有两种常见实现逻辑:
方案1:始终仅保留最新的错误提示(旧提示自动关闭)
改造MessageNotificationService代码如下:
import { MatSnackBarRef } from '@angular/material/snack-bar'; @Injectable({ providedIn: 'root' }) export class MessageNotificationService { // 存储当前打开的snackbar实例 private currentSnackbar: MatSnackBarRef<any> | null = null; constructor( public snackBar: MatSnackBar, private zone: NgZone) { } showError(message: string): void { this.zone.run(() => { // 先关闭已存在的snackbar if (this.currentSnackbar) { this.currentSnackbar.dismiss(); } // 打开新的snackbar并存储实例 this.currentSnackbar = this.snackBar.open(message, 'X', { panelClass: ['error'], verticalPosition: "top", horizontalPosition: "center" }); // snackbar关闭后清空实例标记 this.currentSnackbar.afterDismissed().subscribe(() => { this.currentSnackbar = null; }); }); } }
方案2:已有提示展示时,直接跳过新的错误提示
仅需修改showError里的判断逻辑即可:
showError(message: string): void { // 已有打开的snackbar则直接返回 if (this.currentSnackbar) return; this.zone.run(() => { this.currentSnackbar = this.snackBar.open(message, 'X', { panelClass: ['error'], verticalPosition: "top", horizontalPosition: "center" }); this.currentSnackbar.afterDismissed().subscribe(() => { this.currentSnackbar = null; }); }); }
二、停止错误/异常的传播
你可以在全局ErrorHandler中添加错误已处理标记,避免同一个错误被重复触发处理,同时也可以根据需求决定是否把错误输出到控制台:
改造GlobalErrorHandler代码如下:
@Injectable() export class GlobalErrorHandler implements ErrorHandler { constructor(private errorService: ErrorService, private messageNotificationService: MessageNotificationService) { } handleError(error: Error | HttpErrorResponse | any) { // 已经处理过的错误直接跳过,避免重复处理 if (error.__handled) return; // 标记错误已处理 error.__handled = true; if (error instanceof HttpErrorResponse) { // 处理服务端接口错误 } else { // 处理客户端错误 const message = this.errorService.getClientErrorMessage(error); this.messageNotificationService.showError(message); } // 如果不需要错误继续向上抛到控制台,就不要执行下方代码 // super.handleError(error); // 或者 console.error(error); } }
如果是循环逻辑中主动抛出的错误,你也可以在业务代码的循环外层加try/catch捕获异常,避免错误持续抛到全局错误处理器。
内容的提问来源于stack exchange,提问作者Enis
相关产品推荐
相关产品推荐

