Как правильно возвращать и получать преобразованные данные из наблюдаемой службы и компонента Angular? - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть базовая служба, настроенная для работы в качестве наблюдаемой.

Я внедрил службу в компонент, который подписывается на следующий метод службы, который запускает HTTP-запрос данных:

listApi(params:any) Observable<any[]> {
...
return this.http.get(params.url, ampOptions)
                    .map(data => this.listExtract(response, params))
                    .catch(this.handleError);
}

Мне нужно перебрать и преобразовать ответ таким образом, чтобы он гарантированно завершил до возврата его моему компоненту.

Для достижения этой цели я попытался использовать функцию async с await и Promise.all:

async listExtract(response:any, params:any) {
  let newArray:any = [];
  await Promise.all(response.map((item, index) => {
      if(item.id === params.id) {
       // make changes to specific item if it's id is a match
       item.label = 'selected';
      }
      newArray.push(item);
  });
  // i am assuming the above promise.all is guaranteed
  // to complete before returning the new array, correct??
  return newArray;
}

В моем компоненте я подписываюсь на метод listApi в моем сервисе:

this.listService.listApi(params)
      .subscribe(
        response => this.listServiceResponse(response),
        error => this.serviceError = <any>error);

Ответ появляется , чтобы пройти правильно, но поскольку я использую обещание для преобразования данных, он обернут в объект под названием ZoneAwarePromise:

listServiceResponse(response) {
   // because i used an async function in the service,
   // Angular returns the response wrapped in an
   // object titled ZoneAwarePromise
   console.log('response:',response);
}

Если мой подход, описанный выше с использованием функции async , действителен для предварительного преобразования данных, как мне правильно получить этот ответ? Или я должен идти об этом совершенно по-другому?

Я мог бы просто извлечь ответ из объекта ZoneAwarePromise, но это не кажется надежным, и просто в качестве примера следующее работает , но это не может быть правильным способом иди об этом:

listServiceResponse(response) {
       // attempt to use a .then to extract the data
       response.then((extractedArray) => {
         console.log('response:',extractedArray);
       }
}

Есть ли другой подход, который, возможно, использует более сложный метод отображения?

ЛЮБЫЙ очень признателен за помощь.

1 Ответ

0 голосов
/ 30 апреля 2018

Вы должны иметь возможность использовать наблюдаемое напрямую. Метод подписки не сработает, пока контент не будет возвращен вашим сервисом, поэтому вы должны быть в состоянии выполнить всю необходимую обработку, прежде чем он будет вызван. Я думаю, что вы можете упростить ваш listExtract, чтобы он просто занимался преобразованием ответа в ваш массив вещей, не беспокоясь об асинхронном бизнесе.

listExtract(response:any, params:any): any[] {
  let results: any[] = response.results;
  return results.map(item => {
    if (item.id == params.id)
      item.label = 'selected';
    return item;
  });
}

Тогда ваш listApi метод может оставаться в основном таким же, но вы должны использовать тот аргумент data, который у вас есть, который будет http-ответом.

listApi(params:any) Observable<any[]> {
  return this.http.get(params.url, ampOptions)
                    .map(data => this.listExtract(data, params))
                    .catch(this.handleError);
}

Тогда использование этого вызова службы listApi должно быть достаточно простым в вашем компоненте:

this.listService.listApi(params)
      .subscribe(array_of_things = this.workWithMyList(array_of_things));

Наблюдаемое здесь должно устранить любую необходимость вручную обрабатывать асинхронную природу ваших данных. Когда ваша подписка сработает, данные уже будут там.

...