Angular - 如何调用具有多个订阅者/主题的 HTTP 调用

Angular - How to call make an HTTP Call that has multiple subscribers / subjects

抱歉,标题令人困惑,措辞困难。

我有一个 angular 服务调用 API 并获取页面列表。这些页面是从多个组件订阅的。考虑到这一点,我使用 BehaviorSubjects 来确保每个订阅者都能获得更新。

当我想添加一个新页面时,我需要向服务器提交一个 HTTP POST 请求,然后处理响应。在处理它时,我需要更新数组,然后调用 next() 将更新发送给订阅者。这要求我在 HTTP 调用上有一个订阅者(至少我认为是这样),以便我可以调用 next()。但是,在调用next的同时,我也希望组件更新并让用户知道它已完成。

这是一个 stackblitz 示例。 app.component.ts 第 38 行调用了创建页面的服务。下面注释掉的是一段代码,它会订阅并将 isSaving 变量设置为 false。但是,我无法订阅该方法,因为它已经在 pages.service.ts 文件中订阅了。

https://stackblitz.com/edit/angular-abi4mn

我希望这个例子比我的胡言乱语更有意义,如果解释不当,我们深表歉意。

目前您订阅了 PagesService 中的可观察对象,调用该方法的组件应该改为订阅它。因此,在您的 PagesService.add 中,您应该 return observable 并且您可以在调用组件中订阅 observable:this.pagesService.add(newPage).subscribe(...).

现在由于您还想在 POST 请求成功后在您的 PagesService 中做一些事情,您可以 spy 观察到的结果而不影响它使用tap 运算符,像这样:

页面服务:

public add(page): Observable<any> {
 return this.httpClient
  .post('https://my-json-server.typicode.com/typicode/demo/posts', page)
  .pipe(
     tap(() => {
        this.pages.push(page);
        this._pages.next(this.pages);
     }),
  );
}

如果要更新同一页面上的页面数组,请使用 _pages observable 而不是局部变量 page。您只需要进行三处更改。

<p>
  In the real life example there will be multiple subscribers to the pages array on the pages service.  When I add to the array, i need to contact the backend server as well as, update the array so the subscribers can pick up the change.  
  </p>
  <p>
  As well as updating the array, it would be nice for the component thats submitting the call to know when the save has completed.  This way i can display some visual information to the user.  In this example i use the isSaving variable.  This is the part i dont know how to handle, i want to add to the pages array, but also have the component subscribe to the http call so that it can do some stuff once the call is complete.
  </p>
  <p>

  Number of Pages: <strong>{{(pagesService._pages | async).length}}</strong> <br />  <br />
  <button (click)="addPage()" [disabled]="isSaving">Add Page</button>
</p>

将 private 设置为 public 以将 _pages 变量投入服务。

public _pages = new BehaviorSubject<any[]>([]);

第三个变化需要更新 isSaving 变量。

public getPages() {
    this.pagesService.get().subscribe((result: any[]) => {

      this.pages = result;
this.isSaving = false;
    }, error => {

      console.error(error);
    });
  }

我已经测试了所有场景并且工作正常。 如果您有任何疑问,请告诉我。 谢谢