эффективная фильтрация массива наблюдаемых - PullRequest
1 голос
/ 08 мая 2019

Я изучаю официальный учебник по угловым вопросам (https://angular.io/tutorial/toh-pt4). Извините за низкий уровень: (

Я пытаюсь изменить сервис, который возвращает список героев ... Как наблюдаемые объекты rxjs, потому что это самый эффективный способ сделать это

hero.service.ts
==============

import {Injectable} from '@ angular / core';

import {Observable, of} from 'rxjs';

import {Hero} from './hero';
import {HEROES} from './mock-heroes';
import {MessageService} from './message.service';

@Injectable ({
  providedIn: 'root',
})
export class HeroService {

  constructor (private messageService: MessageService) {}

  getHeroes (): Observable <Hero []> {
    // TODO: send the message _after_ fetching the heroes
    this.messageService.add ('HeroService: fetched heroes');
    return of (HEROES);
  }
}

mock-heroes
===========

import {Hero} from './hero';

export const HEROES: Hero [] = [
  {id: 11, name: 'Mr. Nice '},
  {id: 12, name: 'Narco'},
  {id: 13, name: 'Bombast'},
  {id: 14, name: 'Celeritas'},
  {id: 15, name: 'Magneta'},
  {id: 16, name: 'RubberMan'},
  {id: 17, name: 'Dynama'},
  {id: 18, name: 'Dr IQ'},
  {id: 19, name: 'Magma'},
  {id: 20, name: 'Tornado'}
];

Я хочу иметь сервис, который возвращает только героя, когда я передаю идентификатор

import {Injectable} from '@ angular / core';
import {Hero} from './hero';
import {HEROES} from './mock-heroes';
import {Observable, of} from 'rxjs';
import {MessageService} from './message.service';
import {map} from 'rxjs / operators';

@Injectable ({
  providedIn: 'root'
})
export class HeroService {

  private heroes: Observable <Hero []>;

  getHeroes (): Observable <Hero []> {
    this.messageService.add ('HeroService: fetched heroes');
    // return of (HEROES);
    this.heroes = of (HEROES);
    return this.heroes;
  }

  getHeroeById (id: number): Observable <Hero> {
    this.messageService.add ('A hero is queried with id' + id);
    

    return this.heroes.pipe (map (x => x.id === id));
  }

  constructor (private messageService: MessageService) {}

 / * getHeroes (): Hero [] {
    return HEROES;
  } * /

  //builder() { }
}

ОШИБКА в src / app / hero.service.ts (26,5): ошибка TS2322: тип «Наблюдаемый» не может быть назначен типу «Наблюдаемый». Тип «логический» нельзя назначить типу «Герой». src / app / hero.service.ts (26.40): ошибка TS2339: свойство 'id' не существует для типа 'Hero []'.

Вы можете мне помочь?

Ответы [ 3 ]

2 голосов
/ 08 мая 2019

У вас есть пара вариантов. Вы можете использовать Array.find () или Array.filter ()

Array.filter ()

getHeroeById (id: number): Observable <Hero> {
  this.messageService.add('A hero is queried with id: ' + id);

  // Filter heroes to get heroById
  return this.heroes.filter(x => x.id == id)[0];
}

Array.find ()

getHeroeById (id: number): Observable <Hero> {
  this.messageService.add('A hero is queried with id: ' + id);

  // Find hero by Id.
  return this.heroes.find(x => x.id == this.personId);
}
1 голос
/ 08 мая 2019

Ваша проблема в этой строке:

return this.heroes.pipe (map (x => x.id === id));

вы используете оператор rx map, который работает и преобразует элементы в потоке, а элемент потока в этом случае представляет собой фактический массив героев. Вы возвращаете результат проверки того, равно ли какое-либо несуществующее свойство id массива параметру id, который является логическим значением. Вот почему вы видите ошибки, которые вы есть.

В этом случае вы должны использовать оператор поиска массива для массива в потоке, поскольку вы хотите найти этот элемент в массиве, например:

return this.heroes.pipe (map (heroes => heroes.find(h => h.id === id)));

таким образом, вы возвращаете фактический результат операции поиска массива в операции преобразования карты rx.

Следующее, вы не инициализируете свой heroes наблюдаемый до тех пор, пока не будет вызван getHeroes(). Это может быть преднамеренным, но кажется, что вместо этого вы должны сделать это в конструкторе, чтобы сначала можно было безопасно вызвать getHeroeById().

1 голос
/ 08 мая 2019

Вы хотите вернуть героя в списке героев с соответствующим идентификатором, попробуйте заменить

return this.heroes.pipe (map (x => x.id === id));

на

return this.heroes.pipe (map (heroes => heroes.find( hero => hero.id === id));
...