Как обработать ax ios httpservice наблюдаемый ответ? - PullRequest
1 голос
/ 29 марта 2020

Я думаю, что схожу с ума, потому что я довольно плохо знаком с нодами и машинописью ... Я просто хочу синхронно получить результат запроса 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
  }
}

edit : Я пишу здесь полный код, так как он может быть полезен для других, изучающих фреймворк. Я использовал ответ Джея, но Ричбай также очень помог мне в понимании теории. Конечно, улучшайте / исправляйте, если это все еще может стать лучше.

  1. Я добавил тип, чтобы иметь лучший контроль вместо объекта
  2. Мне нужно было изменить поле даты из ответа от " yyyy-mm-ddThh24: mi: ss "to" yyyy-mm-dd "
  3. Мне также нужно было отфильтровать ответ по значению

     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]}))),
    );
    }
    

Ответы [ 2 ]

2 голосов
/ 29 марта 2020

РЕДАКТИРОВАТЬ:

Отказ от ответственности: Я не знаю много конкретно о Nest, поэтому этот ответ с чисто ванильной точки зрения JS, разные библиотеки имеют разные встроенные способности. Далее следует объяснение различных способов обработки асинхронных запросов и наблюдаемых в javascript. Я также настоятельно рекомендую читать асинхронные javascript, наблюдаемые и обещания, поскольку это сделает ваше время в javascript гораздо более приятным.

Веб-запросы в javascript происходят асинхронно, что означает, что они выполняются чаще или менее параллельно с остальной частью вашего синхронного кода. Вы можете представить это как отдельную ветку, хотя это не так. Это означает, что код, основанный на значении этого веб-запроса, должен останавливаться до тех пор, пока запрос не будет завершен. Из моего исходного поста ниже, самый простой вариант в вашем случае, вероятно, вариант 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);

Из параметров опция 3 позволяет вам использовать asyn c и ожидать, что не является синхронным, но позволяет обрабатывать остальную часть кода в методе asyn c как будто это так, так что это может быть ближе всего к тому, что вы хотите. Я лично считаю, что вариант 2 - ваш лучший вариант, поскольку вы сохраняете всю функциональность наблюдаемых объектов, включая весь набор доступных вам операторов. Примите асинхронный код в javascript, это лучшее и зачастую единственное решение многих проблем.

1 голос
/ 29 марта 2020

Если вам нужно сделать это из службы Nest и вернуть результат обратно клиенту, вы можете просто вернуть наблюдаемое, и Nest обработает для вас подписку оттуда. Если вам необходимо выполнить дополнительную обработку данных, вы можете использовать оператор map после оператора .pipe() для Observable. Примером этого может быть получение только данных из ответа топора ios, а не всего ответа (что может иметь проблемы с JSON.stringify(), поскольку оно имеет циклические ссылки на себя).

Ниже приведен пример такого

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

@Injectable()
export class HttpConsumingService {
  private readonly DATA_URL = 'http://remote/data.json';
  constructor(private readonly http: HttpService) {}

  callHttp(): Observable<Array<Object>> {
    return this.http.get(this.DATA_URL).pipe(
      map((axiosResponse: AxiosResponse) => {
        retrun axiosResponse.data;
      })
    );
  }
}

Здесь, если у вас есть контроллер, который вызывает this.httpConsumingService.callHttp(), Nest вызовет службу, подпишется на наблюдаемое и вернет Данные от него под капотом. Никакой дополнительной работы не требуется. Если вам нужна дополнительная информация об Observables и доступных операциях, learnrx js .io - довольно хороший источник.

...