I have 2 observable: initialLessons$
and searchLessons$
.
The initialLessons$ displays a completed http fetch request of courses initially.
The searchLessons$ request is an observable fromEvent
that listens on button click keyup
event and executes after a button click on the search filter button (with a filter parameter).
Now, if I have this.lessons$ = concat(initialLessons$, searchlessons$)
, normally, the operator concat from rxjs first executes the first observable, then waits for it to complete, before executing the second observable.
If I have already completed the first observable on initial request, does it "skip" the completed observable and execute the second observable only, e.g if I launch a search request on button click? Or will it again execute the first observable in the pipe and then the others sequentially? Because that would be a waste of ressources...
And same, if I only e.g execute the first observable, and the second has already completed (or is unnecessary to execute), will it still execute the second (and all others in the parameter list)?
CodePudding user response:
If I have already completed the first observable on initial request, does it "skip" the completed observable and execute the second observable only, e.g if I launch a search request on button click? Or will it again execute the first observable in the pipe and then the others sequentially? Because that would be a waste of ressources...
Yes, it does "skip" the completed observable(s). Concat works like you mentioned, concat will subscribe to the-i if and only if i-1 observable is completed. So now every time click a button, lesson$ will emit the event.
And same, if I only e.g execute the first observable, and the second has already completed (or is unnecessary to execute), will it still execute the second (and all others in the parameter list)?
This question does not make sense (not in an offending way by the way), because if the i observable never completed, how the i 1 already completed? The keyword here is concat WILL SUBSCRIBE to every parameters.
CodePudding user response:
I've just built this very simple sample on codepen.io and it re-executes the completed observable:
const first = of(1,2)
first.subscribe()
const second = of(3,4)
concat(first, second).subscribe(console.log) // Prints 1,2,3,4
What you could do to avoid re-executing the request would be to "cache" emissions from the first observable by using shareReplay(1)
which would maintain in-memory the last emission of the piped observable:
const first = of(1,2).pipe(
shareReplay(1)
)
first.subscribe()
const second = of(3,4)
concat(first, second).subscribe(console.log) // Prints 2,3,4
CodePudding user response:
In this case you may want to look at shareReplay
operator.
If I understand the problem right, this could be a possible approach
First you create a new Observable for fetch with shareReplay
const initialLessonsShareReplay$ = initialLessons$.pipe(
// shareReplay tells to repeat the last value notified (if available)
// when the Observable returned by the pipe is subscribed
shareReplay(1),
// we take 1 just to make sure that the Observable is completed
take(1)
)
Now you subscribe this initialLessonsShareReplay$ in the initial request and wait for it to notify something.
When it comes the time to use the concat
function, you will have something like this
concat(initialLessonsShareReplay$, searchLessons$)
If initialLessonsShareReplay$
has already notified a value, then this value will be immediately notified as soon as the Observable returned by concat
is subscribed and therefore you will have only to wait for searchLessons$
to notify.
A similar approach can be used to manage the case where searchLessons$
has already notified something.