Reputation: 68740
(FYI: Angular+Typescript)
I have a function that needs to return cheap Observable 1 if it has anything, otherwise expensive Observable 2.
I use Race to pick the faster one, but that's not ideal as the http calls start then are killed.
get(): Observable<Cat> {
let cachedValues$ = (gets from fast cache)
let serverValues$ = (gets from expensive server)
return race(cachedValues$, serverValues$);
}
Upvotes: 0
Views: 1309
Reputation: 3594
If your cache$
is an Observable with 1 or 0 value, you can do
return cache$.pipe(
first(),
catchError(() => server$),
);
You don't need first()
operator if your cache$
already return an error when it has no value.
Upvotes: 1
Reputation: 20454
You can use concat to set up a sequence of observables. Assuming that each of your sources will emit one result and then complete, you can pipe to the find operator with the condition that the value isn't empty.
Find will return the first emission that passes the predicate and then complete. It is unique from first and take(1) in that if the condition is never met the last result will be returned so you always get a result.
get(): Observable<Cat> {
let cachedValues$ = (gets from fast cache)
let serverValues$ = (gets from expensive server)
return concat(cachedValues$, serverValues$).pipe(find(x => !!x));
}
Upvotes: 2
Reputation: 4107
Try using switchMap... I assume what you have is pseudocode.
This will attempt to get from the cachedValues observable, and if the result is falsy it will return the serverValues observable. Otherwise, it will return the cache result wrapped as an observable, since switchMap must return an observable.
import { of } from 'rxjs'
const cachedValues$ = fastObservable;
const serverValues$ = slowObservable;
return cachedValues$.pipe(
switchMap(cacheHit => {
if (!cacheHit) {
return serverValues$;
}
return of(cacheHit);
})
)
Upvotes: 1
Reputation: 4993
I suppose this would work:
get(): Observable<Cat> {
let serverValues$ = (gets from expensive server)
let cachedValues$ = (gets from fast cache);
return cachedValues$.pipe(
switchMap(value => {
return value ? of(value) : serverValues$;
})
);
}
Upvotes: 4