如何在Angular 5中使用rxJS存储来自API的可观察数据?

Gab*_*urt 0 observable rxjs behaviorsubject angular

我有一个角度服务,可以从API获取数据,并且此数据在许多组件中使用,因此每次调用API来获取相同数据都是浪费的。

因此,我继续尝试使用BehaviorSubjects来存储数据。我很好地工作了一点,像这样使用它:

服务内容

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

组件:

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

有书籍时,它工作正常,但是如果书籍是一个空数组(这是预期的行为之一),则程序将陷入循环,并永远调用api。测试它,我发现它被卡在服务调用的.do()部分中,但是我不知道为什么。

在这里读到BehaviorSubject并不是要使用空初始值,而是像建议的@estus一样,使用ReplaySubject(1)也会发生同样的事情。

我想知道是否存在“正确”的方式来存储数据。我也不认为使用localstorage是最好的解决方案,因为它可能会存储大量数据,并且在使用应用程序时会发生很大变化。

Lyn*_*242 5

这样做:

服务

// 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);
       } );
  }
Run Code Online (Sandbox Code Playgroud)

TS文件

ngOnInit() {
    this.booksService.getBooks().subscribe(
        (books) => {  
            console.log('books: ', books);
        });
}
Run Code Online (Sandbox Code Playgroud)

这里发生的是,您只会加载一次图书清单。建立对书籍的订阅,并且一旦书籍列表到达,新列表就会传播到所有订户。

因此,您应该看到2次控制台日志。第一个带有空白列表,第二个带有书籍。