Typescript 如何处理axios httpservice可观察响应?

Typescript 如何处理axios httpservice可观察响应?,typescript,axios,nestjs,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.

我想我快疯了,因为我对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
  }
}
从'@nestjs/common'导入{Injectable,HttpService};
从'@nestjs/core'导入{};
@可注射()
导出类应用程序服务{
私有只读数据\u URL:字符串=”https://remote/data.json";
构造函数(私有httpService:httpService){}
getSomething():数组{
让resp=this.httpService.get(this.DATA_URL);//我现在该怎么办?它是一个可观察的
}
}
编辑: 我在这里写完整的代码,因为它可能对其他学习框架的人有用。我使用了周杰伦的回答,但里奇白也帮助我理解了背后的理论。当然,如果还可以改进/纠正

  • 我添加了一个类型以更好地控制而不是对象
  • 我需要将响应中的日期字段从“yyyy-mm-ddThh24:mi:ss”更改为“yyyy-mm-dd”
  • 我还需要根据一个值过滤响应

     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]}))),
    );
    }
    
    getSomething(aFilterValue:number):可观察{
    返回此.httpService.get(this.DATA\u URL).pipe(
    map((axiosResponse:axiosResponse)=>(axiosResponse.data as)
    回复[])
    .filter((el:RespDTO)=>el.aCode==aFilterValue)
    .map((el:RespDTO)=>({…el,aDateField:el.aDateField.split('T')[0]})),
    );
    }
    
  • 编辑:

    免责声明:我对Nest不太了解,所以这个答案完全是从普通JS的角度来看的,不同的库有不同的内置功能。下面解释了在javascript中处理异步请求和观察的不同方法。我还强烈建议您阅读异步javascript、可观察性和承诺,因为这将使您在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);
    }
    
    原始答案

    不能以同步方式从可观察对象检索值。您必须订阅它并在返回值后执行某些操作,或者将其转换为承诺并返回承诺。您的选择包括:

    // 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);
    
    //选项1将getSomething更改为doSomething,并使用该方法执行所有操作
    doSomething():数组{
    让resp=this.httpService.get(this.DATA\uURL);
    resp.subscribe((值)=>{//do something})
    }
    //选项2返回可观察对象并在该方法之外订阅它
    getSomething():数组{
    返回this.httpService.get(this.DATA\u URL);
    }
    //在AppService之外,您可以像这样使用它
    appService.getSomething().subscribe((值)=>{//do something})
    //选项3将可观察到的内容转换为承诺并返回
    getSomething():数组{
    返回this.httpService.get(this.DATA_URL).toPromise();
    }
    //在AppService之外,您可以像这样使用它
    让value=wait-appService.getSomething();
    console.log(值);
    

    在这些选项中,选项3允许您使用async和Wait,这不是同步的,但允许您将async方法中的其余代码视为同步,因此这可能最接近您想要的。我个人认为选项2是你最好的选择,因为你保留了所有可观测的功能,包括所有的操作符。采用javascript中的异步代码,这是解决许多问题的最佳且通常是唯一的解决方案。

    如果您需要从Nest服务执行此操作,并将结果返回给客户端,您只需返回可观察的,Nest将从那里为您处理订阅。如果需要进行任何额外的数据处理,可以在
    可观察的
    .pipe()
    操作符之后使用
    映射
    操作符。这方面的一个例子可能是只从axios响应中获取数据,而不是从整个响应中获取数据(这会给JSON.stringify()带来麻烦,因为它本身有循环引用)

    下面是这样一个例子

    从'@nesjts/common'导入{Injectable,HttpService};
    从“axios”导入{AxiosResponse};
    从“rxjs”导入{Observable};
    从“rxjs/operators”导入{map};
    @可注射()
    导出类HttpConsumingService{
    私有只读数据http://remote/data.json';
    构造函数(私有只读http:HttpService){}
    
    callHttp():Observable是一个很好的源代码。

    如果您更熟悉Promises和async/Wait,那么您也可以将HttpService(以及Axios)与Promises一起使用:

    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.
    
    甚至:

    const body = (await this.httpService.get(this.DATA_URL).toPromise()).data;
    

    我使用的是await,但您可以使用经典的promise语法:

    this.httpService.get(this.DATA_URL).toPromise()
    .then(resp => {
        console.log(resp.data);
    })
    .catch(err => {
        // Handle Error Here
        console.error(err);
    })
    

    您尝试过这个吗?您可以将rxjs可观测值转换为承诺(
    .toPromise()
    )例如,简单地等待它。我很困惑…该代码在后端REST控制器中,由外部API调用。我只想让我的服务器检索数据,过滤数据,最后将其返回到客户端…方法2是否可行?只有一个似乎是3,但不明白为什么在服务器端fr中像nest这样的软件使它变得如此复杂:(我添加了这段代码,这似乎是最好的选择,你能告诉我怎么做吗,从axiosResponse.data开始(这是一个数组)我可以对数组元素做进一步的优化?在我看来,关于可观测性的一件大事是,几乎每个操作符都可以在同一个
    .pipe()
    表达式中进行链接,因此可以在同一个管道中使用多个操作符进行优化