NgRx首次触发Effect耗时短,后续触发耗时过长问题求助
问题:Action分发到Effect触发耗时差异过大
我在优化页面时用console.time检测到一个异常:分发LoadBudgetListRequestAction到触发Effect的耗时差异极大——页面首次加载时仅27-50ms,但通过按钮刷新数据时耗时飙升至600-1000ms。不过从分发Action到Reducer的耗时始终小于1ms。
相关代码
分发Action代码
loadBudgets() { console.time('SINCE DISPATCHING UNTIL EFFECT'); console.time('DISPATCHING LoadBudgetListRequestAction until reducer'); this.store$.dispatch( new BudgetListActions.LoadBudgetListRequestAction(), ); }
Reducer代码
case BudgetListActionTypes.BUDGET_LIST_LOAD_REQUEST: { console.timeEnd('DISPATCHING LoadBudgetListRequestAction until reducer'); return { ...state, isLoading: true, error: null, isDataAvailable: false }; }
Effect代码
@Injectable() export class BudgetListStoreEffects { @Effect() loadRequestEffect$ = this.actions$.pipe( ofType( featureActions.BudgetListActionTypes.BUDGET_LIST_LOAD_REQUEST, ), switchMap(() => { console.timeEnd('SINCE DISPATCHING UNTIL EFFECT'); // API CALL }), ); constructor( private budgetApi: BudgetService, private actions$: Actions, private store$: Store<any>, ) { } }
注:我有多个Effect,获取服务器数据后需结合页面过滤器(存储在Store中)筛选数据,猜测后续刷新时Store数据量更大,但每次获取的数据不超过1500条。
排查思路
- 排查其他Effect的同步阻塞:多个Effect并行运行时,刷新阶段如果有其他Effect在执行大量同步逻辑(比如大集合的筛选、转换),会占用主线程,导致当前Effect的触发被延迟。给其他Effect的关键逻辑加上时间打点,定位是否有耗时较长的同步任务。
- 检查Store订阅的开销:刷新后Store数据量增大,所有订阅了Store中过滤器或预算数据的组件/Effect,可能在执行低效的筛选逻辑(比如O(n²)的循环匹配)。逐一排查这些订阅者的处理逻辑,优化算法复杂度。
- 验证RxJS调度器的影响:默认情况下Effect的调度依赖主线程,若主线程被其他任务占用,会延迟Effect的执行。可以在Effect的pipe中添加
observeOn(asyncScheduler),强制异步调度,看是否能缩小耗时差异。 - 排除Redux DevTools的干扰:开启DevTools时,刷新阶段它需要处理更多历史数据,可能拖慢调度速度。关闭DevTools后重新测试,确认是否是这个因素导致的耗时增加。
- 优化组件变更检测:页面刷新时,Store数据变化可能触发大量组件变更检测,占用主线程资源。给相关组件设置
ChangeDetectionStrategy.OnPush,减少不必要的变更检测,释放线程资源。 - 检查内存泄漏与GC:多次刷新后若存在内存泄漏,JS引擎会频繁触发垃圾回收,阻塞主线程。用浏览器Memory面板分析内存变化,确认是否存在内存持续增长的情况,及时修复泄漏点。
内容的提问来源于stack exchange,提问作者Antonio Maciel
相关产品推荐
相关产品推荐

