Skip to content

Interaction of withLatestFrom and combineLatest changes values depending on the subscription order of independent subscribers with shareReplay(1). #6608

Open
@begrs

Description

@begrs

Discussed in #6605

Originally posted by begrs September 20, 2021
Hi, a sample code that produces my issue is here: https://stackblitz.com/edit/rxjs-mvugpe?file=index.ts
image

I have two observables as sources input1$ and input2$. Now when one of them is updated, some computation is triggered in the observable calculated$.
The calculated observable has two subscribers to its value, one of which is combined$. Combined$ also requires the input1$ and input2$ values for its computation (here just a console log).

image
Now one of the inputs is changed to 5. This causes calculated$ to be updated, which in turn updates secondSub and combined$.
What is very weird, is that in combined$ the OLD value of the changed input is used, not the one used for the calculation in calculated$.

However, if I move secondSub (line 12) after combined$, or remove it alltogether, the console long in combined$ actually produces the desired input with the CURRENT value of the changed input.
image
image
Removing the shareReplay(1) also fixes the issue - but that was kind of expected.

After the discussion I know understand the behavior, but it is a dangerous issue for me as it produces silent errors.

Reasoning to open an issue:

For me the correct way of handling withLatestFrom and combineLatest would be to first subscribe to combineLatest observables, since even in other use cases, the combineLatest is kind of a combination of multiple observables as a source and should happen before any piped operator. In some of the use cases it does not make any difference, but would in my opinion be more consistent with how users think it will work.
The current behavior is as you said not obvious and can cause a lot of silent errors in a lot of places.
In my case the only reason I found it at all was a division by zero due to the old value.
The secondSub in my case is located in another typescript file and input1, input2 and calculated are part of a kind of module wide "store" to which all components have access and share their values by.
I know RX.js sometimes behaves that way, but it kind of breaks any separation of concerns approaches when the order of independent subscribers (secondSub and combined have nothing to do with each and have no direct interaction, they only use the same source value) causes different values in the value streams.

Metadata

Metadata

Assignees

Labels

7.xIssues and PRs for version 7.x8.xIssues and PRs for version 8.xbugConfirmed bug

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions