How can I create an RxJs observable that only emits a complete
event and no next
events?
I have an observable that performs some operations which has a side effect in which it populates an in-memory cache. I would like to use this observable as a semaphore so that a second observable only starts executing when it is complete. Then a second observable can use this cache to decorate incoming data. My idea is to use concat where the first observable only emits a complete
event:
const cache = {};
const firstObservable = // fetch data to be cached
const secondObservable = // fetch other data that will be decorated with cached data
// add all next events of the first observable to the cache
const promise = firstObservable
.forEach(
data => {
cache[data.key] = data;
}
);
// create a new observable that only emits a complete event
const waitForCache = of(promise)
.pipe(
// skip the first event from waitForCache (the empty promise event),
// since we are only interested in when the population of the cache is complete
skip(1)
);
// create a semaphore that waits for the complete event from the cache population
// before dealing with the second observable
const decorated = concat(waitForCache, secondObservable)
.pipe(
map(
data => {
// decorate objects with data from cache
return Object.assign({}, data, cache[data.key]);
}
));
My assumption is that the problem is the skip(1)
call.
waitForCache
completes too early and the cache is empty when the second observable attempts to fetch the value. Notably, the cache will be populated after the decoration has been made. waitForCache
observable will add an additional (empty) event to the decorated
observable I decided to re-implement my solution to subscribe to both observables and then use a filter to discard the events from the firstObservable
(that were added to the cache) so that only the events from the secondObservable
are affected by the mapping function:
const cache = {};
const firstObservable = // fetch data to be cached
const secondObservable = // fetch other data that will be decorated with cached data
// add all next events of the first observable to the cache
const waitForCache = firstObservable
.pipe(
tap({
next: data => {
cache[data.key] = data;
}
});
// use concat so the cache population is completed before dealing with the second observable
const decorated = concat(waitForCache, secondObservable)
.pipe(
filter(
data => { return /* check for some specific property that is
available in one observable, but not the other */ }
)
map(
data => {
// decorate objects with data from cache
return Object.assign({}, data, cache[data.key]);
}
));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.