Reputation: 30212
I have an observable with interesting data that changes over time (BehaviorSubject
):
const obs = ...
Then I have a click action (Subject
which gets called .next()
upon button press):
const clickAction = ...
I wish to do this:
obs.pipe(sample(clickAction)).subscribe(data => console.log(data))
The problem I have is this: when I click my button multiple times in a row, it only logs the message once to the console. If obs
changes, then clicking again will once again log to the console.
Expected behavior: the data (whether it has changed or not) should also be logged every time I click the button.
I thought sample
was supposed to do this, but I reckon there must be a better way to do this?
Upvotes: 1
Views: 62
Reputation: 30212
I ended up implementing this:
export function upon<T>(notifier: Observable<any>): MonoTypeOperatorFunction<T> {
return (source: Observable<T>) => {
const latest = withLatestFrom(source)(notifier)
const mapper = map(([, source]: [any, T]) => source)
return mapper(latest)
}
}
Which can be used like so: obs.pipe(upon(clickAction))
Upvotes: 1
Reputation: 14109
sample
isn't working in your case because:
sample
looks at the source Observable and emits whichever value it has most recently emitted since the previous sampling, unless the source has not emitted anything since the previous sampling.
Use withLatestFrom
to combine click events with the latest emitted value from your source observable.
clickAction.pipe(
withLatestFrom(obs),
map(([notifier, source]) => source)
).subscribe(console.log)
https://stackblitz.com/edit/typescript-uxizci
Upvotes: 1