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

如何使用rxJS在Angular 5中存储API中的可观测数据?,angular,rxjs,observable,behaviorsubject,Angular,Rxjs,Observable,Behaviorsubject,我在angular中有一个从API获取数据的服务,这些数据在许多组件中使用,因此每次调用API获取相同的数据都是一种浪费 所以我继续尝试使用BehaviorSubjects来存储数据。我很好地工作到了一定程度,使用方式如下: 服务: books = new BehaviorSubject<Book[]>(null); setBooks(book: Book[]) { this.books.next(book); } getBooks() { this.http.get

我在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);
        }
    );
}
当有书籍时,它可以正常工作,但是如果书籍是一个空数组(这是预期的行为之一),程序就会陷入循环,永远调用api。通过测试,我发现它在服务调用的.do()部分卡住了,但我不知道为什么

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

我想知道是否有一种“正确”的方法来存储这样的数据。我也不认为使用localstorage是最好的解决方案,因为它可能包含大量数据,并且随着应用程序的使用,它会发生很大的变化。

这样做:

服务

// 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);
       } );
  }
ngOnInit() {
    this.booksService.getBooks().subscribe(
        (books) => {  
            console.log('books: ', books);
        });
}
这里发生的是,您将只加载一次图书列表。图书订阅已建立,一旦图书列表到达,新列表将传播到所有订阅者

所以您应该看到2次控制台日志。第一个列表为空,第二个列表为书。

按以下方式操作:

服务

// 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);
       } );
  }
ngOnInit() {
    this.booksService.getBooks().subscribe(
        (books) => {  
            console.log('books: ', books);
        });
}
这里发生的是,您将只加载一次图书列表。图书订阅已建立,一旦图书列表到达,新列表将传播到所有订阅者


所以您应该看到2次控制台日志。第一个列表为空,第二个列表为书。

如果没有书,您想怎么办?因为,如果条件是在空值情况下导致永久循环的原因,请看我的答案。这可能是你正在寻找的。如果没有书,你想做什么?因为,如果条件是在空值情况下导致永久循环的原因,请看我的答案。这可能就是你要找的。嗯,有意思,我要在这里测试一下。但是如果这些书不是空的,并且它们已经更新了,比如说,用户创建了一本新书。更改会通过所有订阅的组件传播吗?实际上,经过测试,它在所有情况下都可以正常工作。谢谢嗯,有意思,我要在这里测试一下。但是如果这些书不是空的,并且它们已经更新了,比如说,用户创建了一本新书。更改会通过所有订阅的组件传播吗?实际上,经过测试,它在所有情况下都可以正常工作。谢谢