Получить последний накопленный результат сканирования вместо повторения? - PullRequest
0 голосов
/ 11 декабря 2018

Приведенный ниже код выполняет следующие действия:

  1. Загрузите полный набор книг, позвонив по номеру backendService.backendService возвращает результат как ReplaySubject(10), возвращая 600 книг в каждом выданном значении, примерно 8 раз.Причина возврата результата в чанках состоит в том, чтобы быстро предоставить пользователю некоторые данные, поскольку для получения каждого чанка требуется более секунды.
  2. Затем метод loadBooks выбирает заголовок книги и накапливает испущенноемассивы в один полный список книг.
  3. Метод findBooksByFilter используется компонентом списка книг.Он возвращает наблюдаемый отфильтрованный массив названий книг.

Вопрос, который у меня возникает, состоит в том, что я должен делать по-другому, чтобы не повторять операцию scan каждый раз, когда я вызываю метод findBooksByFilter.На самом деле меня интересует только последнее накопленное значение из _books$ наблюдаемой.

export class BookService  {

  constructor(private backendService: BackendService) {
    this.loadBooks();
  }

  private _bookCategoryRid = '6662c0f2.ee6a64fe.25cm75kl2.m4fvotr.e7t9hb.l892ddpqqi2971ldvj4ea';

  private _books$ = new Observable<string[]>();

  private loadBooks(): void {
    this._books$ = this.backendService.getBookDtosByCategory(this._bookCategoryRid).pipe(
      scan<AssetSearchResultItem[], string[]>((acc, curr) => {
        const v = curr.map(val => val._name);
        return acc.concat(v);
      } , [])
    );
  }

  public getBooks(): Observable<string[]> {
    return this._books$;
  }

  public findBooksByFilter(searchPhrase: string): Observable<string[]> {
    if ( !searchPhrase.trim() || searchPhrase.length < 1) {
      return this._books$;
    }
    return this._books$.pipe(
      map(
        books => {
          console.log(books);
          return books.filter(
            book => ( term.indexOf(searchPhrase) >= 0));
          }
    ));
  }


}

1 Ответ

0 голосов
/ 11 декабря 2018

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

Один из способов сделать это - использовать shareReplay(1) оператор.Он буферизует столько уведомлений, сколько указано в значении параметра, и отправляет их каждому новому подписчику сразу же при подписке.При значении, равном 1, оно отправляет последнее полученное уведомление, превращая его в своего рода «кеш» (который раньше был именем оператора, но у фактического кеша гораздо больше параметров конфигурации).

С вашим кодом это будет:

this._books$ = this.backendService.getBookDtosByCategory(this._bookCategoryRid).pipe(
  scan<AssetSearchResultItem[], string[]>((acc, curr) => {
    const v = curr.map(val => val._name);
    return acc.concat(v);
  } , []),
  shareReplay(1)
);
...