在NestJS中如何使用外部API返回的Observable类型数据?
问题原因
你当前的核心问题有两个:
- NestJS内置的
HttpService基于RxJS封装,调用请求后返回的是Observable类型,本身不是Promise,直接用await无法解析得到实际接口返回值 - 你给
getPrestacionById方法加了async修饰符,导致原本返回的Observable被自动包装成了Promise<Observable<IPrestacion>>,await执行后拿到的就是未解析的Observable对象,自然无法直接访问detalles属性
解决方案
有两种常用的处理方式,你可以根据项目场景选择:
方案1:将Observable转为Promise,兼容async/await写法
RxJS 7+ 提供了firstValueFrom/lastValueFromAPI用于将Observable转为Promise,替代已废弃的toPromise方法。
修改PIntegration类代码如下:
import { firstValueFrom, map } from 'rxjs'; @Injectable() export class PIntegration { constructor(private httpService: HttpService) { } API = process.env.API || 'http://localhost:3000'; header = { headers: { 'Content-Type': 'application/json' } }; async getPrestacionById(id: string): Promise<IPrestacion>{ const request$ = this.httpService.get(`${this.API}/prestacion/${id}`, this.header).pipe( map((res) => res.data) ); // 等待Observable触发第一个值就resolve return firstValueFrom(request$); } }
修改后你原本ProductService中的await调用逻辑不需要做任何调整,就能直接拿到解析后的接口返回对象,正常访问detalles属性。
方案2:直接使用Observable订阅逻辑
如果你不想转Promise,可以保留Observable返回类型,去掉多余的async修饰符,通过订阅或者RxJS操作符处理数据:
首先调整PIntegration的方法定义:
import { map } from 'rxjs'; @Injectable() export class PIntegration { constructor(private httpService: HttpService) { } API = process.env.API || 'http://localhost:3000'; header = { headers: { 'Content-Type': 'application/json' } }; getPrestacionById(id: string): Observable<IPrestacion>{ return this.httpService.get(`${this.API}/prestacion/${id}`, this.header).pipe( map((res) => res.data) ); } }
之后调整ProductService的逻辑,用操作符处理数据:
import { tap } from 'rxjs'; @Injectable() export class ProductService{ constructor(private pIntegration: PIntegration){} producto(id: string): Observable<IPrestacion> { return this.pIntegration.getPrestacionById(id).pipe( tap(infoPrestacion => { console.log({ infoPrestacion }) if (infoPrestacion?.detalles) { console.log(infoPrestacion.detalles) console.log("tiene detalles") } }) ); } }
注意:如果该方法最终是被NestJS控制器调用,直接返回Observable即可,框架会自动订阅并把最终值返回给客户端,不需要额外处理。
注意事项
如果你的项目使用的是RxJS 6及更早的版本,暂时可以用toPromise()替代firstValueFrom,但建议升级RxJS到7+的稳定版本使用新API,避免后续兼容性问题。
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

