【问题标题】:How to store observable data from API with rxJS in Angular 5?如何在 Angular 5 中使用 rxJS 存储来自 API 的可观察数据?
【发布时间】:2018-11-19 13:42:42
【问题描述】:

我有一个从 API 获取数据的 Angular 服务,并且这些数据用于很多组件,所以每次调用 API 来获取相同的数据是一种浪费。

所以我继续尝试使用 BehaviorSubjects 来存储数据。我工作得很好,像这样使用它:

服务

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() 部分,但我不知道为什么。

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

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

【问题讨论】:

  • 没有书你想做什么?因为,您的 if 条件是在空值的情况下导致永远循环的原因
  • 请看我的回答。这可能就是您要搜索的内容。

标签: angular rxjs observable behaviorsubject


【解决方案1】:

这样做:

服务

// 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 次控制台日志。第一个是空列表,第二个是书籍。

【讨论】:

  • 嗯,有趣,我要在这里测试一下。但是,如果书籍不是空的,并且它们已经更新,假设用户创建了一本新书,该怎么办。更改会通过所有订阅的组件传播吗?
  • 实际上,经过测试,它适用于所有情况。谢谢!
猜你喜欢
  • 2018-10-25
  • 1970-01-01
  • 2017-06-11
  • 2022-01-02
  • 2020-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-01
相关资源
最近更新 更多