Reputation: 6612
I think I'm getting crazy as I'm pretty new to node and typescript...I simply want to retrieve, in a syncronous way, the result of an http get request.
Given:
import { Injectable, HttpService } from '@nestjs/common';
import {} from '@nestjs/core';
@Injectable()
export class AppService {
private readonly DATA_URL:string = "https://remote/data.json";
constructor(private httpService:HttpService){}
getSomething(): Array<Object> {
let resp = this.httpService.get(this.DATA_URL); //what do I do now?? It's an observable
}
}
edit: I'm writing here the full code as it could be useful to others learning the framework. I used Jay's response, but richbai also helped me a lot in understanding the theory behind. Of course improve/correct if it can still get better.
I also needed to filter the response based on a value
getSomething(aFilterValue:number): Observable<RespDTO[]> {
return this.httpService.get(this.DATA_URL).pipe(
map((axiosResponse : AxiosResponse) => (axiosResponse.data as
RespDTO[])
.filter((el:RespDTO) => el.aCode===aFilterValue)
.map((el:RespDTO) => ({...el,aDateField:el.aDateField.split('T')[0]}))),
);
}
Upvotes: 10
Views: 25730
Reputation: 1526
Can can use the follow code:
execute = async (): Promise<BondAssetType[]> => {
var response : Observable<BondAssetType[]> = this._assetBondTypeService.findAll().pipe(map(x => x.data));
var result:BondAssetType[] = await firstValueFrom(response);
return result;
}
Upvotes: -1
Reputation: 70131
If you are needing to do this from a Nest service, and return the result back to the client, you can simply return the observable and Nest will handle the subscription for you from there. If you need to do any extra data processing you can use the map
operator after the .pipe()
operator of an Observable
. An example of this could be getting only the data from the axios response and not the entire response (which would have trouble with JSON.stringify()
because it has circular references on itself).
The following is an example of such
import { Injectable, HttpService } from '@nesjts/common';
import { AxiosResponse } from 'axios';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable()
export class HttpConsumingService {
private readonly DATA_URL = 'http://remote/data.json';
constructor(private readonly http: HttpService) {}
callHttp(): Observable<Array<Object>> {
return this.http.get(this.DATA_URL).pipe(
map((axiosResponse: AxiosResponse) => {
return axiosResponse.data;
})
);
}
}
From here, if you have a controller that calls this.httpConsumingService.callHttp()
, Nest will call the service, subscribe to the observable, and return the data from it under the hood. No extra work needed. If you're looking for more info on Observables and the available operations learnrxjs.io is a pretty good source.
Upvotes: 14
Reputation: 462
You can also use HttpService (and so Axios) with Promises, if you are more familiar with promises and async/await thant with Observables :
const resp = await this.httpService.get(this.DATA_URL).toPromise(); // Here you get the AxiosResponse object.
const body = resp.data; // Here you get the response body, which is automatically parsed in the .data property of the AxiosResponse.
Or even :
const body = (await this.httpService.get(this.DATA_URL).toPromise()).data;
I am using await, but you could use classic promise syntax :
this.httpService.get(this.DATA_URL).toPromise()
.then(resp => {
console.log(resp.data);
})
.catch(err => {
// Handle Error Here
console.error(err);
})
Upvotes: 0
Reputation: 5204
EDIT:
Disclaimer: I don't know much about Nest specifically, so this answer is from a purely vanilla JS perspective, different libraries have different built in abilities. What follows is an explanation of different ways to handle asynchronous requests and observables in javascript. I also highly recommend reading up on asynchronous javascript, observables, and promises as it will make your time in javascript far more pleasant.
Web requests in javascript happen asynchronously, meaning that they execute more or less in parallel with the rest of your synchronous code. You can imagine it like a separate thread, although it is not. This means that code that relies on the value from this web request must stall until the request is complete. From my original post below, the simplest option in your case is probably option 3. The code to use it might look a bit like this:
/**
* A method in your rest controller that relies on the getSomething()
* method as implemented in option 2 below
*/
async showRemoteData() {
const remoteData = await appService.getSomething();
// replace console.log with whatever method you use to return data to the client
console.log(remoteData);
}
Original Answer
You cannot retrieve a value from an observable in a synchronous way. You have to subscribe to it and do something once the value has been returned, or convert it to a promise and return the promise. Your options are these:
// option 1 change getSomething to doSomething, and do everything in that method
doSomething(): Array<Object> {
let resp = this.httpService.get(this.DATA_URL);
resp.subscribe((value) => { // do something })
}
// option 2 return the observable and subscribe to it outside of that method
getSomething(): Array<Object> {
return this.httpService.get(this.DATA_URL);
}
// outside of the AppService you can use it like this
appService.getSomething().subscribe((value) => {// do something})
// option 3 convert the observable to a promise and return it
getSomething(): Array<Object> {
return this.httpService.get(this.DATA_URL).toPromise();
}
// outside of the AppService you can use it like this
let value = await appService.getSomething();
console.log(value);
Of the options, option 3 allows you to use async and await which is not synchronous but allows you treat the rest of your code in the async method as though it is, so that might be closest to what you want. I personally think option 2 is your best option though as you keep all the functionality of observables, including the whole sweet of operators available to you. Embrace asynchronous code in javascript, it is the best and often times only solution to many problems.
Upvotes: 5