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
相关产品推荐
相关产品推荐

