如何使用NestJS从第三方API获取数据

时间:2020-04-26 23:25:45

标签: axios nestjs

我最近开始学习NestJS,因为它似乎是帮助构建我的项目后端的绝佳框架。我需要学习的是查找来自第三方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成功构建了所有内容而没有错误。但是,当我去邮递员并尝试达到终点时,我得到了:

nest-weather app postman error

我认为我已经非常仔细地跟踪了NestJS文档,并使用了自己在Axios上的经验,但是我无法弄清楚我在这里做的不正确。我有一个较大的项目,想在其中使用Nest,但是我需要点击一个第三方API才能使该项目正常工作。

有什么想法吗?

谢谢!

更新: 使用Observable的pipe方法和catchError之后,我的状态为401。起初,我以为这意味着我的api密钥未正确传递,但是我注销了该密钥,它与我的weather api帐户中的内容匹配。

第二次更新:几天后(包括一个晚上的休假),我仍然没有任何成功。如果我将URL和API密钥移到weather.services.ts中,则会得到一个循环引用。我已经阅读过Nest和Axios的文档,并且感觉像这样,但仍然无法正常工作。

我还尝试访问Nest通过axiosRef()公开的HttpService,但最终遇到Typescript编译错误,将我的Observable类型转换为Promise。所做的只是给我另一个通函。

1 个答案:

答案 0 :(得分:0)

在您的服务中,当您返回输出时,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;
         }),
      );
  }
}