combineLatest 使用的一个陷阱和基于 debounceTime 的解决方案

简介: combineLatest 使用的一个陷阱和基于 debounceTime 的解决方案

首先了解 combineLatest 这个操作符的作用:

组合多个 Observable 以创建一个 Observable,其值是根据其每个输入 Observable 的最新值计算得出的。

其弹珠图如下图所示:


我们有一个限制值流和一个偏移值流。 我们使用 combineLatest 组合这些流以创建一个流,该流将在每次源流之一更改时具有一个新值。 然后我们使用 switchMap 根据这些值从后端获取数据以获取 pokemon$。 因为我们使用了switchMap,如果一个调用还没有结束,那么当一个新的调用通过改变limit或者offset来发起一个新的调用时,前一个调用就会被取消。


代码如下:

this.pokemon$ = combineLatest(limit$, offset$)
       .pipe(
        map(data => ({limit: data[0], offset: data[1]})),
        switchMap(data => this.pokemonService.getPokemon(data.limit, data.offset)),
        map((response: {results: Pokemon[]}) => response.results),
      );

代码地址如下:

https://stackblitz.com/edit/angular-deqtkx

当我修改 limit 和 offset 为其他值之后,点击 reset 按钮,此时会观察到先后发起两个请求,并且第一个请求自动被 cancel 的情况:

通过单击重置按钮,我们通过同时重置限制和偏移值来更新我们的两个源流。 这个动作的效果是 combineLatest 创建的流触发了两次,因此启动了两个后端请求,另一方面,由于我们使用了 switchMap,立即取消了一个。


我们来单步拆解,以加深印象:


combineLatest 保存所有源流的最后一个值。比如开始场景是,limit = 8,offset = 2)

单击重置按钮

limit 设置为 5

combineLatest 看到一个新值进入 limit 并发出一个新组合,limit = 5,offset = 2

switchMap 获取这些值并订阅触发后端调用的流

偏移量设置为 0

combineLatest 看到一个新的 offset 值,并发出一个新的组合,limit = 5,offset = 0

switchMap 获取这些值,取消订阅(并因此取消)先前的请求并开始新的请求

在此流程中您可能没有预料到的是,无论何时设置 limit ,此更改都会在更改 offset 之前直接传播到 combineLatest.


如何避免这个行为

如果有一种方法可以确保在同一个调用堆栈中发生的更改(这是单击重置按钮时发生的情况)被丢弃以支持最后一次更改,我们可以解决我们的问题。


这意味着,当 combineLatest 在同一个调用堆栈中发出两个值时,当调用堆栈被清除时,最后一个值将被发送。


为此,我们可以在 combineLatest 之后直接利用值为 0 的 debounceTime。 这将确保只有最后一个值被传递给 switchMap,并且在调用堆栈被清除之后。


每当提到“在同一个调用堆栈中”时,都可以将其替换为“在事件循环的同一轮次中发生的更改”。


加上了 debounceTime(0) 之后的时序图:


combineLatest 保存所有源流的最后一个值,开始场景是,limit = 8,offset = 2

单击重置按钮

限制设置为 5

combineLatest 运算符看到一个新值进入 limit 并发出一个新组合,limit = 5,offset = 2

debounceTime 运算符看到一个新值,并且(因为操作符的值为 0)将等待直到调用堆栈被清除以将其传递

偏移量设置为 0

combineLatest 运算符看到一个新的 offset 值,并发出一个新的组合,limit = 5,offset = 0

debounceTime 运算符再次看到一个新值,将丢弃旧值,并等待堆栈被清除以将其传递

调用堆栈被清除

debounceTime 运算符没有看到新的值,将通过组合,limit = 5,offset = 0 向下游发送数据

switchMap 操作符获取这些值并订阅触发后端调用的流

修复代码非常简单,加上一行代码即可:

debounceTime(0),

修复后的效果,点击 reset 按钮之后,只有一次 HTTP 请求发出了:

相关文章
|
12天前
|
存储 人工智能 安全
数字化转型的10大陷阱及如何避免
数字化转型的10大陷阱及如何避免
|
1月前
|
安全
编程高级陷阱-破坏原有生态
编程高级陷阱-破坏原有生态
|
1月前
|
程序员 测试技术
程序员难以一次性写好代码并持续修复Bug,主要源于软件的高复杂性、需求不确定性、测试局限性和技术能力限制。
【5月更文挑战第11天】程序员难以一次性写好代码并持续修复Bug,主要源于软件的高复杂性、需求不确定性、测试局限性和技术能力限制。复杂的系统易产生意外问题,需求变化导致初始设计难完备,测试无法覆盖所有情况,而技术更新和个体能力差异也会引入错误。因此,持续调试和优化是保证软件质量的关键步骤。
27 0
|
7月前
|
移动开发 运维 开发者
探索开发过程中的技术陷阱:掉入新技术的“巨坑”
在快速发展的技术领域,开发人员经常面临着学习和采用新技术的挑战,尤其是随着卓越工程的逐步推进,越来越多的底层技术升级迭代被正式投入使用。而这些新技术和新特性带来了非常多的好处和便利,但是当作为开发者的我们去追求这种改变、开心的使用这些新技术的时候,可能会无意识地掉入一些陷阱或者“巨坑”。开发者在自己开发经历中肯定会遇到因为没有深入了解新技术的实现原理而开心地误入陷阱,成为新技术的“小白鼠”,那么本文就来简单唠唠开发中的技术“巨坑”,以及爬坑过程经验分享。
46 0
探索开发过程中的技术陷阱:掉入新技术的“巨坑”
|
编译器 C语言
源于《C陷阱与缺陷》----研究程序死循环问题
所以最后答案应该就是打印了12次xiao tao,然后越界访问出现错误,使arr[10]=0,arr[11]=0了 但最后答案却不是这样。
94 0
|
数据采集 人工智能 数据管理
开始数据治理时三个常见的陷阱和解决方法
当我们与客户合作帮助他们提高数据管理能力时,大多数部门都同意更好的数据治理将有助于解决他们的数据问题。
开始数据治理时三个常见的陷阱和解决方法
combineLatest 使用的一个陷阱和基于 debounceTime 的解决方案
combineLatest 使用的一个陷阱和基于 debounceTime 的解决方案
95 0
combineLatest 使用的一个陷阱和基于 debounceTime 的解决方案
|
存储 人工智能 算法
数据创新的四个陷阱
数据的重要性在当今已经无需在多言,所有的企业都意识到数据的重要性,都希望利用数据来驱动业务的发展。但是,很多企业信息化管理者依然存在对于数据智能,数据驱动的一些误解,这些误解会让企业的数据利用陷入深渊。
2918 0
数据创新的四个陷阱
|
Web App开发 JavaScript 前端开发
容易忽视的前端陷阱
1 CSRF CSRF(Cross Site Request Forgery)是伪造客户端请求的一种攻击,字面上的意思是跨站点伪造请求 CSRF的定义是强迫受害者的浏览器向一个易受攻击的Web应用程序发送请求,最后达到攻击者所需要的操作行为。
866 0
关于企业费控管理的这些陷阱,你知道吗?
快速发展的企业对费用管控的关注点应该在费用发生的合理性和有效性!因为,快速发展的企业,很难有一套体系能够适应它的变化,如果有了体系可能也就是限制了它的发展。
8605 0