Как хранить наблюдаемые данные из API с помощью rxJS в Angular 5? - PullRequest
0 голосов
/ 10 июня 2018

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

Так что япошел вперед и попытался использовать объекты поведения для хранения данных.Я работал хорошо до некоторой степени, используя это так:

Сервис :

books = new BehaviorSubject<Book[]>(null);
setBooks(book: Book[]) {
    this.books.next(book);
}
getBooks() {
    this.http.get(...).do(
        (res) => {
            this.setBooks(res.books);
        }
    );
}

Компоненты:

ngOnInit() {
    this.booksService.books.subscribe(
        (books) => {
            // in case the api was never called
            if (books == null) {
                return this.booksService.getBooks().subscribe();
            }
            console.log(books);
            // ...
        }
    );
}

Работает нормально, когда есть книги, но если книги представляют собой пустой массив (что является одним из ожидаемых вариантов поведения), программа застревает в цикле, вызывая API навсегда.Тестируя его, я понял, что он застревает в части .do () в служебном вызове, но я понятия не имею, почему.

Я прочитал здесь BehaviorSubject не предназначен для использования с нулемначальное значение, но, как предложил @estus, при использовании ReplaySubject (1) происходит то же самое.

Интересно, есть ли «правильный» способ хранения данных, подобный этому.Я также не думаю, что использование localstorage является лучшим решением, так как это может быть большой объем данных, и он сильно меняется по мере использования приложения.

1 Ответ

0 голосов
/ 10 июня 2018

Сделайте это следующим образом:

Сервис

// init books as BehaviorSubject with an empty array of type Book
books = new BehaviorSubject<Book[]>([]);

setBooks(book: Book[]) {
     this.books.next(book);
}

 // return books as an Observable
 getBooks(): Observable<Book[]> {
     // only if length of array is 0, load from server
     if (this.books.getValue().length === 0) {
          this.loadBooks();
     }

     // return books for subscription even if the array is yet empty. 
     // It‘ll get filled soon.
     return this.books.asObservable();  
  }  

  private loadBooks(): void {
      this.http.get(...).do(
         (res) => {
             this.books.next(res.books);
       } );
  }

Файл TS

ngOnInit() {
    this.booksService.getBooks().subscribe(
        (books) => {  
            console.log('books: ', books);
        });
}

Что происходитЗдесь вы можете загрузить список книг только один раз.Подписка на книги устанавливается, и как только появляется список книг, новый список распространяется среди всех подписчиков.

Таким образом, вы должны увидеть журнал консоли 2 раза.Первый с пустым списком, а второй с книгами.

...