Как создать сервис, который получает значения асинхронно, но также выполняет задачи с этими данными, такие как фильтрация? - PullRequest
0 голосов
/ 29 июня 2019

У меня есть служба ", предоставленная в корне ", которая:

  • получает данные один раз от API
  • должна обрабатывать сопоставление этих данных
  • должен предоставлять эти данные другим компонентам, если это необходимо

Эти данные не нужно перезагружать в течение всего жизненного цикла приложения.Он загружается только тогда, когда пользователь обновляет браузер.Все данные будут использоваться в какой-то момент - поэтому нет смысла делать http-запросы для каждого getOneById().В этом случае фильтр работает быстрее.

Макет сервиса выглядит примерно так:

export class MyTypeService {
  items: MyType[] = [];
  items$ = new BehaviorSubject<MyType[]>(this.items);

  constructor(private http: HttpClient) { }

  getData(): Subscription {
    return this.http.get<SearchResult>(
      'path'
    ).pipe(
      map((response: any) => {
        this.items = response;
        return this.items;
      }),
      catchError(error => {
        // removed from the question for simplicty
        this.handleError(error);
        return of([]);
      })
    ).subscribe(result => this.items$.next(result));
  }

  getOneById(id: string): MyType|null {
    for (let item of this.items) {
      if (item.id === id) {
        return item;
      }
    }

    return null;
  }
}

Теперь я заблудился с этими вопросами:

  • Должна ли сама служба подписаться на items$?
    или , если все функции-члены, такие как getOneById() подписаться?
    (что может означать, что я могу удалить items.
  • Должен ли я вызывать getData() в конструкторе, так как мне определенно нужны значения во время запуска приложения?
    Или следует ли вызывать его в первый раз, когда значения действительно нужны?
  • Как мне сказать компоненту, что использовать безопасно getOneById()?

1 Ответ

1 голос
/ 29 июня 2019

У вас не должно быть предметов без Observable вообще.Нечто подобное должно работать, чтобы вы не делали http-запрос, когда он вам не нужен

  itemsSub: BehaviorSubject<any[]> = new BehaviorSubject(null);

  getItems(): Observable<any[]> {
    return this.itemsSub.pipe(mergeMap(items => {
      if (items) {
        return of(items); // Return items if you already have them
      } else {
        // If you don't have them, get them and emit on subject
        return this.http.get().pipe(tap((items) => this.itemsSub.next(items))); 
      }
    }))
  }

  getItemsFiltered() {
    return this.getItems().pipe(filter(items => !!items));
  }
...