Angular 11使用combineLatest为Invoice对象赋值重复触发问题
重复触发原因
combineLatest 触发规则为:所有源流至少触发过1次值之后,任意一个源流更新值都会触发下游回调。你当前场景仅需要在用户点击新增发票、nextInvoiceNumber$ 更新时才执行发票创建逻辑,invoiceBatch$ 和 currentUser$ 的更新不需要触发创建动作,用combineLatest 不符合业务场景才会出现重复触发,大概率是另外两个初始化流在组件加载后又更新了一次值,导致多触发一次回调。
解决方案
替换为 withLatestFrom 操作符即可,该操作符仅会在主源流更新时,取其他辅助流的最新值合并输出,辅助流自身更新不会触发下游,完全匹配你的业务需求。
优化后的组件代码
import { withLatestFrom, map, takeUntil, Subject } from 'rxjs'; // 组件销毁触发器,避免内存泄漏 private destroy$ = new Subject<void>(); // 主源流为nextInvoiceNumber$,仅当它更新时才取另外两个流的最新值 newInvoice$ = this.nextInvoiceNumber$.pipe( withLatestFrom(this.invoiceBatch$, this.userService.currentUser$), // 直接映射为新的Invoice对象,符合声明式写法,避免全局对象引用问题 map(([invoiceNumber, invoiceBatch, currentUser]) => ({ fdInvoiceNumber: invoiceNumber, fdInvoiceBatchID: invoiceBatch.fdInvoiceBatchID, fdFiscYearPer: invoiceBatch.fdFiscYearPer, fdCreatedByID: +currentUser.fdApplicationUserID, fdCreatedBy: currentUser.fdUserName } as Invoice)) ); ngOnInit() { this.newInvoice$ .pipe(takeUntil(this.destroy$)) .subscribe(newInvoice => { this.invoiceService.CreateInvoice(newInvoice); }); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); }
额外说明
你最初combineLatest 没有响应的原因也是它的规则限制:需要所有源流都至少触发过一次值才会启动,nextInvoiceNumber$ 是普通Subject,只有用户第一次点击调用接口之后才会触发第一次值,所以之前不会执行赋值逻辑,替换为withLatestFrom 后也不存在这个问题。
内容的提问来源于stack exchange,提问作者John Chandler
相关产品推荐
相关产品推荐

