You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NgRx Effect触发10次错误后停止运行的原因及解决方法

问题原因

NgRx Effects内部默认带有错误重试机制:当某个Effect抛出未捕获错误时,它会自动尝试重新订阅该Effect的流,默认重试次数是10次。当10次重试全部失败后,NgRx会终止整个Effects模块的根订阅——这意味着所有Effect都会停止监听Action流,自然第11次分发Action时没有任何反应,Redux DevTools也因为Action流监听中断停止记录。

解决办法

1. 在Effect内部捕获处理错误(最推荐)

在可能抛出错误的操作符(比如mergeMap)内部添加catchError,确保错误不会冒泡到Effects的根订阅。这样单个错误只会影响当前这次Action的处理,不会中断整个Effect或其他Effect的运行。
示例代码:

import { EMPTY } from 'rxjs';
import { catchError } from 'rxjs/operators';

let i = 0

@Injectable()
export class Effects {
    testEffect$ = createEffect(
        () =>
            this.actions$.pipe(
                tap(() => console.log("action number:", i += 1)),
                mergeMap(() => 
                    throwError(() => "").pipe(
                        catchError((err) => {
                            // 这里做错误处理:打印日志、发送错误Action等
                            console.error("Effect执行出错:", err);
                            // 返回EMPTY或其他合法Observable,让流继续运行
                            return EMPTY;
                        })
                    )
                ),
            ),
        { dispatch: false, useEffectsErrorHandler: true },
    )

    // ...
}

2. 自定义全局错误重试策略

如果需要调整默认的重试次数或逻辑,可以在EffectsModule.forRoot()中配置全局错误处理,自定义重试规则,避免重试耗尽后终止根订阅:

import { EffectsModule } from '@ngrx/effects';
import { retry, catchError } from 'rxjs/operators';
import { EMPTY } from 'rxjs';

@NgModule({
  imports: [
    // ...
    EffectsModule.forRoot([Effects], {
      effectErrorHandler: (error$) => error$.pipe(
        retry(5), // 自定义重试5次,替代默认10次
        catchError(() => EMPTY) // 重试耗尽后返回空流,不终止根订阅
      )
    })
  ]
})
export class AppModule { }

3. 关闭默认错误处理(不推荐)

将useEffectsErrorHandler设为false可以关闭NgRx的默认错误重试,但这样未捕获的错误会直接冒泡到应用根区域,可能导致整个应用崩溃,除非你已经实现了全局错误捕获机制。

内容的提问来源于stack exchange,提问作者Andreas T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 13:55:28