1

I am using nestjs and would like to write a function returning Observable (rxjs) with cache.

import { HttpService } from '@nestjs/axios';
import { CACHE_MANAGER, Inject, Injectable } from '@nestjs/common';
import { Cache } from 'cache-manager';
import { map, of, Observable } from 'rxjs';

interface User {
  id: string;
  // ...
}

@Injectable()
export class Service {
  constructor(
    @Inject(CACHE_MANAGER) protected cache: Cache,
    protected readonly httpService: HttpService,
  ) {}
  fetchUser = (id: string): Observable<User> {
    const url = 'xxx';
    const user: string = this.cache.get(`user:${id}`); // but here is `Promise<string>` actually
    if (user) {
      return of(JSON.parse(user) as User);
    }

    return this.httpService.get<User>(url).pipe(
      map(({ data }) => {
        this.cache.set(`user:${id}`, JSON.stringify(data));
        return data;
      })
    );
  }
}

The logic is quite simple, if there is cache, return cache, otherwise call api, save to cache, and return result. The only issue is that cache would return a promise. How to make this work?

1 Answer 1

2

You could use RxJS from function to convert the Promise to an Observable. From there, you could use switchMap operator + of function to either return the user fetched from the cache or make a HTTP call.

fetchUser(id: string): Observable<User> {
  const url = 'xxx';

  const user$ = this.httpService.get<User>(url).pipe(
    map(({ data }) => {
      this.cache.set(`user:${id}`, JSON.stringify(data));
      return data;
    })
  );

  return from(this.cache.get(`user:${id}`)).pipe(
    switchMap((user: string) => 
      !!user ? of(user) : user$
    )
  );
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.