如何使用NestJS从3rd-party API获取数据

问题描述 投票:0回答:2

我最近开始学习 NestJS,因为它似乎是一个很棒的框架,可以帮助构建我的项目后端。我需要学习但找不到的是一种从 3rd-party API 获取数据的方法。根据文档,它包装了 Axios,这很棒,因为我非常了解 Axios。我不明白的是如何让它发挥作用。

出于学习目的,我正在尝试从 OpenWeatherMap.org 获取天气数据。当我搭建应用程序时,我使用了

nest new weather-app
并按顺序生成了天气模块、服务和控制器,以确保所有内容都与
nest g <<<type of file>>> weather
正确集成。您可以放心地假设我的
app.module.ts
正确导入了我的
weather.module.ts
。另外,我的 OpenWeatherMap API 密钥会直接复制到我的
.env
中。

这是我的

weather.module.ts

require('dotenv').config();
import { Module, HttpModule } from '@nestjs/common';
import { WeatherService } from './weather.service';
import { WeatherController } from './weather.controller';

@Module({
  imports: [
    HttpModule.register({
      baseURL: 'api.openweathermap.org/data/2.5/weather',
      params: {
        appid: process.env.OPEN_WEATHER_KEY,
      },
    }),
  ],
  providers: [WeatherService],
  controllers: [WeatherController],
})
export class WeatherModule {}

这是我的

weather.service.ts
:

import { Injectable, HttpService } from '@nestjs/common';
import { AxiosResponse } from 'axios';
import { Observable } from 'rxjs';

@Injectable()
export class WeatherService {
  constructor(private readonly httpService: HttpService) {}

  forCity(city: string): Observable<AxiosResponse<object>> {
    return this.httpService.get(`?q=${city}`);
  }
}

这是我的

weather.controller.ts

import { Controller, Get, Param } from '@nestjs/common';
import { WeatherService } from './weather.service';

@Controller('weather')
export class WeatherController {
  constructor(private readonly weatherService: WeatherService) {}

  @Get(':city')
  getWeather(@Param('city') city: string): object {
    return this.weatherService.forCity(city);
  }
}

当我运行这个项目时,Nest 成功构建了所有内容,没有错误。然而,当我去 Postman 并尝试到达终点时,我得到了这个:

我认为我已经相当仔细地遵循了 NestJS 文档,并利用了我自己使用 Axios 的经验,但我无法弄清楚我在这里做得不正确。我有一个更大的项目,我想在其中使用 Nest,但我需要使用第 3 方 API 才能使该项目正常工作。

有什么想法吗?

提前致谢!

更新: 使用 Observable 的

pipe
方法和
catchError
后,我得到了
401
状态。起初,我认为这意味着我的 api 密钥没有正确传递,但我将其注销,它与我帐户中的天气 api 相匹配。

第二次更新:几天后(包括一个晚上的休息),我仍然没有取得任何成功。如果我将 url 和 API 密钥移至

weather.services.ts
,我会得到循环引用。我已经彻底阅读了 Nest 和 Axios 的文档,但感觉我仍然无法让它工作。

我还尝试访问 Nest 通过

axiosRef()
公开的
HttpService
,但最终收到 Typescript 编译错误,将我的
Observable
类型转换为
Promise
。所做的只是给了我另一个循环引用。

axios nestjs
2个回答
13
投票

HttpModule 和 HttpService(来自“@nestjs/common”包)已被弃用,并将在下一个主要版本中删除。请改用“@nestjs/axios”包。

app.module.ts

import { HttpModule } from '@nestjs/axios';

@Module({
  imports: [
    HttpModule,
  ],
})
export class AppModule {}

app.controller.ts

@Get()
getWeatherForecasts() {
   return this.appService.getWeatherForecasts();
}

app.service.ts

import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';

async getWeatherForecasts() {
   const url = 'http://www.7timer.info/bin/api.pl?lon=113.17&lat=23.09&product=astro&output=json';
   const { data } = await firstValueFrom(this.httpService.get(url));
   return data;
}


3
投票

在您的服务中,当您返回输出时,NestJS 会尝试“字符串化”Observable 类型的输出。这会导致错误,因为上面的返回类型是循环结构。我建议通过管道传递响应。

尝试这个

weather.service.ts

import { Injectable, HttpService } from '@nestjs/common';
import { AxiosResponse } from 'axios';
import { Observable } from 'rxjs';

@Injectable()
export class WeatherService {
  constructor(private readonly httpService: HttpService) {}

  forCity(city: string): Observable<AxiosResponse<object>> {
    return this.httpService
      .get(`?q=${city}`)
      .pipe(
         map((axiosResponse: AxiosResponse) => {
           return axiosResponse.data;
         }),
      );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.