Tips for incorporating promise/async within a function that returns an Observable

I am a user of nestjs and I am currently trying to create a function that returns an Observable (rxjs) with cache functionality.

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 userFromCache: string = this.cache.get(`user:${id}`); // however, it actually returns `Promise<string>`
    if (userFromCache) {
      return of(JSON.parse(userFromCache) as User);
    }

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

The concept behind this logic is straightforward - check if there is cached data, if so return it, otherwise make an API call, store the result in the cache, and return the data. The only hurdle faced is that the cache method returns a promise. Is there a way to overcome this obstacle?

Answer №1

To efficiently handle Promise to Observable conversion, consider utilizing the RxJS from function in your code. Additionally, you can incorporate the switchMap operator along with the of function for seamless user data retrieval from cache or API 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$
    )
  );
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to maintain the order of variadic types for conditionally inferred conditional types?

Here is the type definition that I am working with: type Inner<Type> = Type extends Wrapper<infer U>[] ? U[] : never; Additionally, I have a function with the following signature: function myFunc<From extends Wrapper[], To>( values: ...

What is the process of converting TypeScript to JavaScript in Angular 2?

Currently diving into the world of Angular 2 with TypeScript, finding it incredibly intriguing yet also a bit perplexing. The challenge lies in grasping how the code we write in TypeScript translates to ECMAScript when executed. I've come across ment ...

Having trouble with a 'Could not find a declaration file for module' error while using my JavaScript npm package?

I recently released a JavaScript npm package that is functioning properly. However, when importing it into another application, there always seems to be three dots in front of the name, along with an error message that reads: Could not find a declaration f ...

What is the method for retrieving context data using useContext in the primary/overall component?

Check out the codesandbox for this code. I have been able to successfully pass and update context data within the child components. However, I am facing an issue where I am unable to access this data in the parent component. Any insights on why this might ...

When using `useSWR`, it will return { null, null } for a successful request

When attempting to query the Firebase real-time database using useSWR in my next.js project, I encounter a perplexing issue where both the data and error variables always return as null. import useSWR from 'swr'; const LastSales: NextPage = () = ...

Error message in Angular 2 RC-4: "Type 'FormGroup' is not compatible with type 'typeof FormGroup'"

I'm currently facing an issue with Angular 2 forms. I have successfully implemented a few forms in my project, but when trying to add this one, I encounter an error from my Angular CLI: Type 'FormGroup' is not assignable to type 'typeo ...

Stopping all child events upon clicking (when navigating to a different tab) in RxJS

Currently, I am fetching all the designs (let's say 100) from the database and iterating through them. For each design, I am fetching the design image using a child component. <div *ngFor="let design of designs"> <div (click)="sho ...

A convenient utility for generating React components with pre-populated Tailwind CSS classes

When it comes to extracting local Tailwind-styled components, I tend to do it like this: const Container: React.FC = ({ children }) => ( <div className="bg-white px-5 py-5"> {children} </div> ); To simplify this process, I ...

Exploring methods of utilizing Jasmine to test switchMap in Angular with RxJS

Within my Angular application, I've implemented the following code snippet in one of my components: delete(post: PostInterface): void { const delete$ = this.appDataService.proxy .delete(post, this.paginate) .pipe(switchMap(() => t ...

Issue with accessing form in Angular 6 Reactive forms for custom validator functionality

I am facing an issue with creating a password validation for reactive forms in Angular. Every time I try to verify the password, I get a “Cannot read property 'get' of undefined” error in the console. I have tried different methods to access ...

The TypeORM connection named "default" could not be located during the creation of the connection in a Jest globalSetup environment

I've encountered a similar issue as the one discussed in #5164 and also in this thread. Here is a sample of working test code: // AccountResolver.test.ts describe('Account entity', () => { it('add account', async () => { ...

Adding custom type definitions for an untyped npm module in TypeScript 2

Despite attempting various methods recommended in other sources, I am struggling to configure a TypeScript project that utilizes an untyped NPM module. Below is a simplified example along with the steps I have taken. Let's imagine, for this demonstra ...

Having trouble retrieving data from a Postgres table in my Node Express app, despite using async/await functionalities

Trying to fetch a row from my Postgres database table by id has presented an issue. The function calling the query contains data, but the controller is returning null. It appears that the controller is resolving before the query, despite using await in my ...

Generate user-customized UI components from uploaded templates in real-time

Summary: Seeking a solution to dynamically generate UI pages using user-provided templates that can be utilized for both front-end and back-end development across various use cases. Ensuring the summary is at the top, I am uncertain if this question has b ...

What is the best way to utilize JavaScript prototype methods in Angular 2+ templates?

Is it possible to utilize JavaScript global object constructors, such as Array, within the angular 5 view without having to explicitly declare them in the component? In my particular case, I require access to Array.from() directly within the view. Curren ...

Dynamically load components within a modal window

I am looking for a way to dynamically load a custom component inside a modal while keeping it as flexible as possible. Here is an example : -HTML CODE- <button id="floating_button" class="floating_button animation_floating_in" (click)="loadCustomComp ...

Harnessing the power of the bluebird promise library

Within myPeople function, there is a promise function being called as shown below: var myPeople = function(){ var go; return new Promise (function(resolve){ User .getPeople() .then(function(allPeople){ ...

Why does $http.get succeed but I can't retrieve the output?

How can I retrieve the output from my remote server? - After verifying with Firebug, it seems that the JSON output is correct. Below is my approach, aiming for standardization (Plnkr): app.js, controllers.js, factories.js 'use strict'; var name ...

Ensuring the correct limitation of Records within a generic function

I am currently working on defining a generic TypeScript function that can accept a Record<number, boolean> and return the same value. The challenge I am facing is ensuring that the input type remains generic and is reflected accurately in the output. ...

Acquiring information from file within component operation

When a user drags and drops a file, how can I retrieve it from the drop event? HTML file <div (drop)="drop($event)" > drop file here </div> TS file drop (event) { console.log(event.target.files.length); // I need to retrieve the file her ...