Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJS 5 and alternatives to the cache operator

Before upgrading RxJS to 5.0.0-rc.0 I was using .cache() a lot to share a subscription in my Angular application. The great advantage in using this was that any new subscription would get the last published value.

The RxJS team decided to remove it, and now I find myself manually wiring a private BehaviorSubject or ReplaySubject and then calling .asObservable() all the time. This seems like a lot of boilerplate given the easy way we had to do this before.

Am I missing some easier way? I can't find the .replay() operator, and the .share() and .publishReplay() operators don't seem to do this either.

Thanks!

like image 460
Martín Coll Avatar asked Dec 16 '16 02:12

Martín Coll


1 Answers

EDIT July 2022: The original solution worked only with now deprecated operators and was asctually based on a bug in RxJS. For an up to date solution see the updated aswer here Temporarily caching HTTP responses from parametrised requests using RxJS (and Angular).

ORIGINAL ANSWER: This is what I use to show off RxJS. The following example caches the latest mocked HTTP response for 1 second. It's based on RxJS multicasting via publishReplay() and refCount().

var counter = 1;
var updateTrigger = Observable.defer(() => mockDataFetch())
    .publishReplay(1, 1000)
    .refCount()
    .take(1);

function mockDataFetch() {
    return Observable.of(counter++)
        .delay(100);
}

function mockHttpCache() {
    return updateTrigger;
}

mockHttpCache().toPromise()
    .then(val => console.log("Response from 0:", val));

setTimeout(() => mockHttpCache().toPromise()
    .then(val => console.log("Response from 200:", val))
, 200);

setTimeout(() => mockHttpCache().toPromise()
    .then(val => console.log("Response from 1200:", val))
, 1200);

setTimeout(() => mockHttpCache().toPromise()
    .then(val => console.log("Response from 1500:", val))
, 1500);

setTimeout(() => mockHttpCache().toPromise()
    .then(val => console.log("Response from 3500:", val))
, 3500);

See live demo: https://jsbin.com/todude/3/edit?js,console

This prints to console:

Response 0: 1
Response 50: 1
Response 200: 1
Response 1200: 2
Response 1500: 2
Response 3500: 3
like image 63
martin Avatar answered Oct 23 '22 10:10

martin