Pha*_*ate 3 typescript axios nestjs
我想我快疯了,因为我对 node 和 typescript 还很陌生……我只是想以同步的方式检索 http get 请求的结果。
鉴于:
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
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:我在这里写了完整的代码,因为它可能对其他人学习框架有用。我用了Jay的回答,但是richbai对我理解背后的理论也有很大帮助。当然,如果它仍然可以变得更好,请改进/纠正。
我还需要根据值过滤响应
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]}))),
);
}
Run Code Online (Sandbox Code Playgroud)如果您需要从 Nest 服务执行此操作,并将结果返回给客户端,您只需返回 observable,Nest 将从那里为您处理订阅。如果你不需要做任何额外的数据处理,你可以使用map后运营商.pipe()的运营商Observable。一个例子可能是只从 axios 响应中获取数据,而不是整个响应(这会遇到问题,JSON.stringify()因为它本身有循环引用)。
下面是这样的一个例子
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;
})
);
}
}
Run Code Online (Sandbox Code Playgroud)
从这里开始,如果您有一个调用 的控制器this.httpConsumingService.callHttp(),Nest 将调用该服务,订阅 observable,并在后台从它返回数据。不需要额外的工作。如果您正在寻找有关 Observables 和可用操作的更多信息,learnrxjs.io是一个非常好的来源。
编辑:
免责声明:我对 Nest 不太了解,所以这个答案是从纯粹的 JS 角度来看的,不同的库有不同的内置功能。下面是对 JavaScript 中处理异步请求和可观察量的不同方法的解释。我还强烈建议您阅读异步 javascript、observables 和 Promise,因为它会让您在 javascript 中度过更加愉快的时光。
JavaScript 中的 Web 请求是异步发生的,这意味着它们或多或少与其余同步代码并行执行。您可以将其想象为一个单独的线程,尽管事实并非如此。这意味着依赖于此 Web 请求的值的代码必须停止,直到请求完成。从我下面的原始帖子来看,您的情况中最简单的选项可能是选项 3。使用它的代码可能看起来有点像这样:
/**
* 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);
}
Run Code Online (Sandbox Code Playgroud)
原答案
您无法以同步方式从可观察对象中检索值。您必须订阅它并在返回值后执行某些操作,或者将其转换为承诺并返回承诺。您的选择是:
// 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);
Run Code Online (Sandbox Code Playgroud)
在这些选项中,选项 3 允许您使用异步和等待,它不是同步的,但允许您将异步方法中的其余代码视为同步,因此这可能最接近您想要的。我个人认为选项 2 是你最好的选择,因为你保留了 observable 的所有功能,包括可供你使用的所有操作符。在 JavaScript 中拥抱异步代码,它是解决许多问题的最佳且通常是唯一的解决方案。