首先了解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/a...我修改limit和offset为其他值后,点击reset按钮,会观察到先后发起了两个请求,并且第一个请求被自动取消:通过点击重置按钮,我们通过同时重置限制和偏移值来更新我们的两个源流。这个action的效果是combineLatest创建的stream触发了两次,所以启动了两个后端请求,另一方面因为我们使用了switchMap,一个立即取消了。下面一步步拆解加深印象:combineLatest保存的是所有源流的最后一个值。例如开始场景是,limit=8,offset=2)点击reset按钮limit设置为5combineLatest看到一个新的值进入limit并发出一个新的组合,limit=5,offset=2switchMap获取那些值并订阅触发后端调用,流偏移设置为0combineLatest看到一个新的偏移值,并发出一个新的组合,limit=5,offset=0switchMap获取这些值,取消订阅(并因此取消)先前的请求并启动一个新的请求你可能不会在此流程中期望的是,无论何时设置限制,此更改都会在更改偏移量之前直接传播到combineLatest。如何避免这种行为如果有一种方法可以确保在同一个调用堆栈中发生更改(这是单击重置按钮时发生的情况)被丢弃以支持最后一次更改,我们就可以解决我们的问题。这意味着当combineLatest在同一个调用堆栈中发出两个值时,当调用堆栈被清除时,最后一个值将被发出。为此,我们可以在combineLatest之后直接利用值为0的debounceTime。这将确保只有最后一个值被传递给switchMap,并且在调用堆栈被清除之后。每当提到“在同一个调用堆栈中”时,它都可以替换为“在事件循环的同一轮中发生的变化”。添加debounceTime(0):combineLatest后的时序图保存了所有源流的最后一个值,开始场景是,limit=8,offset=2点击reset按钮,limit设置为5combineLatest算子看到一个新值输入限制并发出一个新的组合,限制=5,偏移量=2debounceTime运算符看到一个新值并且(因为运算符的值为0)将等待直到调用堆栈被清除以将其传递偏移量设置为0combineLatest运算符看到一个新的偏移值,并发出一个新的组合,limit=5,offset=0debounceTime运算符再次看到一个新值,将丢弃旧值,并等待堆栈被清除以传递给它调用堆栈是cleareddebounceTime算子看不到新值,会通过组合向下游发送数据,limit=5,offset=0。switchMap算子拿到这些值,订阅触发后端调用的流。修复代码很简单,只加一行代码:debounceTime(0),修复后的效果,点击reset按钮后,只发送一次HTTP请求:更多Jerry原创文章在这里:《汪子熙》:
