Я новичок в Nestjs , Typescript и в основном бэкэнд-разработке. И я работаю над простым приложением Weather, где я получаю данные о погоде из Open Weather API.
Я использую встроенный Nest HttpModule
, который оборачивает Axios внутри, а затем использует HttpService
для отправки GET-запроса к Open Weather. Запрос возвращает Observable, что для меня совершенно новость.
Как извлечь фактические данные ответа из наблюдаемого в Injectable service
и вернуть их в Controller
?
Вот моя погода.service.ts
import { Injectable, HttpService } from '@nestjs/common';
@Injectable()
export class AppService {
constructor(private httpService: HttpService) {}
getWeather() {
let obs = this.httpService.get('https://api.openweathermap.org/data/2.5/weather?q=cairo&appid=c9661625b3eb09eed099288fbfad560a');
console.info('just before subscribe');
obs.subscribe((x) => {
let {weather} = x.data;
console.info(weather);
})
console.info('After subscribe');
// TODO: Should extract and return response data f
// return;
}
}
А это Weather.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getWeather() {
const res = this.appService.getWeather();
return res;
}
}
Также может кто-нибудь уточнить, какие типы отсутствуют в моем коде?
RxJS Observables по сути являются расширенными обратными вызовами. Поскольку они работают асинхронно, вам нужно, чтобы ваш код учитывал это. Nest может обработать, если Observable будет возвращен из контроллера и подпишется на него под капотом для вас, поэтому все, что вам нужно сделать в своем сервисе, это что-то вроде этого:
import { Injectable, HttpService } from '@nestjs/common';
@Injectable()
export class AppService {
constructor(private httpService: HttpService) {}
getWeather() {
return this.httpService.get('https://api.openweathermap.org/data/2.5/weather?q=cairo&appid=c9661625b3eb09eed099288fbfad560a').pipe(
map(response => response.data)
);
}
}
map
импортируется из rxjs/operators
и похож на Array.prototype.map
тем, что может принимать значения и преобразовывать их по мере необходимости. Отсюда ваш Controller
просто должен вернуться this.appService.getWeather()
, а Nest позаботится обо всем остальном.
Другой вариант, который у вас есть, — преобразовать наблюдаемое в обещание с помощью .toPromise()
, а затем вы можете использовать свой обычный синтаксис async/await
, что является еще одним допустимым выбором.
RxJS v7 и выше
toPromise()
устарела в RxJS v7. Теперь рекомендуется использовать lastValueFrom(observable)
или firstValueFrom(observable)
вместо наблюдаемой асинхронности.
По состоянию на середину 2022 года toPromise() устарела. RxJS рекомендует использовать либо lastValueFrom(), либо firstValueFrom(). rxjs.dev/deprecations/to-promise
Спасибо, я уже разобрался и преобразовал
toPromise()
, что упростило использование async/await