PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Friday, October 14, 2022

[FIXED] How to use rxjs/Observables inside Nestjs Application w/o Controller

 October 14, 2022     axios, nestjs, rxjs     No comments   

Issue

Nestjs suggests to use the HttpModule, imported from @nestjs/axios to perform requests to external APIs. I understand that the HttpService transforms the responses into Observables.

Goal

Request data from an external API and use the data inside the application.

Problem

I fail to understand how to actually retrieve the data from the request. I read in some other answers, that if you return the observable from a Controller, Nestjs will automatically handle it for you and return the data to the client. That's great, however, I am not using it inside a Controller. I need the data to be available inside the application.

I have a service:

@Injectable()
export class ExampleService {

  // constructor

  getData(): Observable<AxiosResponse<any[]>> {
    return this.httpService.get(`http://some-url.com`);
  }

}

How would use getData() within the application logic to get to the data returned by the Observable ? And would it be better, in that case, to use a plain axios request with Promises and not use the HttpModule ?

The only solution I found so far is using subscribe :

this.httpService.get(`http://some-url.com`)
.subscribe((value) => {
  console.log(value);
});

Which seems to be would end up in a callback hell, compared to all the fancy async ... awaits.


Solution

The Answer

The only solution I found so far is using subscribe

Bingo. That's how it's done :)

Some Elaboration

Which seems to be would end up in a callback hell, compared to all the fancy async ... awaits

Not really. As a library built to be declarative, RxJS makes it easy to structure your callbacks.

async/await is just syntactic sugar for promises and .then. It's a language feature, but even without async/await promises bind to one another nicely and avoid deep nesting and 'callback hell'

So while observables don't (and probably never will) enjoy fist-class language constructs like async/await, that doesn't mean they won't manage some (or a lot) of complexity for you.


The RxJS library is built so that, generally, you should never have to nest subscriptions.

The following is considered an anti-pattern:

stream1().subscribe(value1 => 
  stream2(value1).subscribe(value2 => {
    /* Do something with value2 */
  })
)

It would more idiomatically be written as:

stream1().pipe(
  mergeMap(value1 => stream2(value1))
).subscribe(value2 => {
  /* Do something with value2 */
})

Notice how a level of indentation is removed and you only need to subscribe once?

Observables come with a set of higher-order operators that act as highly customizable .thens for streams of values instead of just individual values.

Another Way: Convert to Promises

Observables are a superset of promises, which means you can turn any promise into an observable but you lose structure if you want to convert an observable into a promise. Often this isn't an issue, but let me explain by analogy.

If promises are a container for a value, then observables are a container for a list of values.

I can take any value and create a list out of it. I'll just have a list of length 1.

a_value = 5
// convert with:
list_values = [a_value]

I can't take any list and create a value out of it. I can take the first value, or the last value (If there's only one, those might be the same), if the list is empty, maybe I need to throw an error? Maybe there's a default value I'd be happy with?

Maybe I have a way to reduce multiple values into a single value. Perhaps I can turn a list of integers into a value by adding them all together.

list_values = [1,2,3,4,5]
// convert with:
value = list_values[0] || 0
// or
value = list_values[list_values.length - 1] || 100
// or
value = sum(list_values)

Back to promises. RxJS has firstValueFrom and lastValueFrom as utility functions that wrap a promise around an observable.

firstValueFrom(
  this.httpService.get(`http://some-url.com`)
).then(value => {
  /* Do something with value */
});

// or with await as syntactic sugar

value = await lastValueFrom(
  this.httpService.get(`http://some-url.com`)
);
/* Do something with value */

These are typically enough for something like an http request (since those only return a single value). More complex approaches tend me be handled on the RxJS side before being converted into a promise.



Answered By - Mrk Sef
Answer Checked By - Marie Seifert (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing