简体   繁体   中英

Emitting result and chaining new request in RXJS

I'm trying to implement a super simple cache in RXJS. The way I want it to work is:

  1. Pull from local storage first and emit the value stored there to the subscriber.
  2. Make a call to a web service to get the latest version of what is stored in local storage.
  3. Save the updated value back to local storage.
  4. Return the latest value back to subscriber.

I tried the following code but it doesn't seem to return until after the call to the service responds. SwitchMap didn't do what I wanted either.

const partnerKey = `partner-${partnerId}`;
const localPartner = JSON.parse(localStorage.getItem(partnerKey));

this.partner$ = of(localPartner)
        .pipe(concatMap(_ => partnersService.getById(partnerId)
          .pipe(tap(partner => {
            localStorage.setItem(partnerKey, JSON.stringify(partner));
            return partner;
          }))));

this.partner$.subscribe(x=> console.log(x));

console.log should be called twice in the example above. I would have thought the concatMap would have multiple emits but maybe I'm understanding it wrong. Thanks for the help!

@kyler-johnson got me on the right track. I mistakenly though that eveything should be pipeable but that's not actually the case. I needed to use an operator outside of a pipe. In this case, I ended up splitting the two data fetches into their own observables and then concatting them.

const partnerKey = `partner-${partnerId}`;

const fetchDataFromLocalStorage$ = of(JSON.parse(localStorage.getItem('partner-' + partnerId)));
const fetchDataFromServer$ = partnersService.getById(partnerId)
        .pipe(tap(partner => localStorage.setItem('partner-' + partnerId, JSON.stringify(partner))));

this.partner$ = concat(fetchDataFromLocalStorage$, fetchDataFromServer$);

You could use expand which emits values directly and gets called recursively with the previous output as input. Return EMPTY after the first execution to end the recursion.

 const { of, EMPTY } = rxjs; const { delay, expand } = rxjs.operators; const fetchLocal = of('from local').pipe(delay(500)) const fetchRemote = of('from remote').pipe(delay(3000)) const source = fetchLocal.pipe( expand((value, index) => index < 1 ? fetchRemote : EMPTY) ); source.subscribe(console.log);
 <script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM