First understand combineLatest What this operator does :
Multiple combinations Observable To create a Observable, Its value is based on each of its inputs Observable Calculated from the latest value of .
The marble diagram is shown in the figure below :
We have a limit value stream and an offset value stream . We use combineLatest Combine these flows to create a flow , The stream will have a new value every time one of the source streams changes . And then we use switchMap According to these values, get data from the back end to get pokemon$. Because we used switchMap, If a call is not over , So when a new call changes limit perhaps offset To initiate a new call , The previous call will be cancelled .
The code is as follows :
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),
);
The code address is as follows :
https://stackblitz.com/edit/a...
When I modified limit and offset After other values , Click on reset Button , At this point, it will be observed that two requests have been initiated , And the first request is automatically cancel The situation of :
By clicking the reset button , We update our two source streams by resetting the limit and offset values at the same time . The effect of this action is combineLatest The created flow triggered twice , Therefore, two back-end requests are initiated , On the other hand , Because we used switchMap, Immediately cancelled a .
Let's disassemble it in one step , To impress :
- combineLatest Save the last value of all source streams . For example, the starting scene is ,limit = 8,offset = 2)
- Click the reset button
- limit Set to 5
- combineLatest See a new value enter limit And send out a new combination ,limit = 5,offset = 2
- switchMap Get these values and subscribe to the stream that triggers the back-end call
The offset is set to 0 - combineLatest See a new offset value , And send a new combination ,limit = 5,offset = 0
- switchMap Get these values , Unsubscribe ( And therefore cancel ) Previous request and start a new request
What you may not expect in this process is , Whenever you set limit , This change will be changed in offset Spread directly to combineLatest.
How to avoid this behavior
If there is a way to ensure that changes occur in the same call stack ( This is what happens when you click the reset button ) Discarded to support the last change , We can solve our problems .
It means , When combineLatest When two values are issued in the same call stack , When the call stack is cleared , The last value will be sent .
So , We can do it in combineLatest After that, the direct utilization value is 0 Of debounceTime. This will ensure that only the last value is passed to switchMap, And after the call stack is cleared .
Whenever it comes to “ In the same call stack ” when , Can be replaced by “ Changes that occur in the same round of the event cycle ”.
Combined with the debounceTime(0) Then the sequence diagram :
- combineLatest Save the last value of all source streams , The starting scene is ,limit = 8,offset = 2
- Click the reset button
- The limit is set to 5
- combineLatest Operator sees a new value enter limit And send out a new combination ,limit = 5,offset = 2
- debounceTime Operator sees a new value , also ( Because the value of the operator is 0) Will wait until the call stack is cleared to pass it
- The offset is set to 0
- combineLatest Operator sees a new offset value , And send a new combination ,limit = 5,offset = 0
- debounceTime Operator sees a new value again , Old values will be discarded , And wait for the stack to be cleared to pass it
- The call stack is cleared
- debounceTime Operator does not see the new value , By combining ,limit = 5,offset = 0 Send data downstream
- switchMap The operator takes these values and subscribes to the stream that triggers the back-end call
The fix code is very simple , Just add a line of code :
debounceTime(0),
The effect after repair , Click on reset After the button , For once HTTP The request was made :
more Jerry The original article of , All in :" Wang Zixi ":