仅当不共享订阅时,AsyncPipe初始值才为null

时间:2019-11-29 18:14:37

标签: angular rxjs ngrx ngrx-store angular-pipe

给出一个看起来像这样的模板

<some-component
  *ngIf="someColdObservable$ | async"
  [result]="someColdObservable$ | async"
></some-component>

以及如下所示的可观察物:

someColdObservable$: this.store.pipe(
  select(isAllowedToDoThis),
  filter(Boolean),
  flatMap(() => apiRequest())
);

someColdObservable$被订阅了两次(如预期的那样),这反过来又发出了两个api调用(这显然是代码的味道,但是现在让我们忽略它)。

在这种情况下,some-component不包含任何null检查,并且如果AsyncPipe在模板中评估apiRequest之前没有发出任何值,则AsyncPipe将返回null。导致some-component抛出cannot access x of null(因为[result]此时仍然为空)see AsyncPipe source for reference

这是所有预期的行为(或者至少在阅读源代码之后),但是,当我尝试通过在shareReplay上添加someColdObservable$来发出两个请求来缓解该问题时,我也解决了[result]apiRequest()发出值之前为null。这对我来说意义不大,因为我希望AsyncPipe仍在此处返回null _latestValue,而cannot access x of null错误仍未解决。但是出于某种原因,添加shareReplay可以解决上述两个问题。

这类似于Angular observable behavior odd when shared,但是,为什么shareReplay可以解决此问题仍未解决。

有人能够指出我在这里缺少什么,为什么AsyncPipenull发出值之前不再返回apiRequest()

感谢任何指针和输入,谢谢!

1 个答案:

答案 0 :(得分:3)

第一种情况:

  1. 计算ngIf表达式。它订阅了可观察对象,并且评估为null。因此,由于ngIf表达式是虚假的,因此不对[result]表达式进行求值。
  2. 可观察对象发出,并且ngIf表达式变为真。因此,对[结果]表达式进行了评估。它自己的异步管道订阅了Cold Observable,后者发送了另一个请求,并求值为null,因此将其作为输入传递给组件。

第二种情况:

  1. 计算ngIf表达式。它订阅了可观察对象,并且评估为null。因此,由于ngIf表达式是虚假的,因此不对[result]表达式进行求值。
  2. observable发出,并且ngIf表达式变为true。因此,对[结果]表达式进行了评估。它自己的异步管道订阅了hot observable,后者立即重播上一次发出的内容,并且不再发送请求。因此,将表达式的值计算为非null值,并将其作为输入传递给组件。

比使用shareReplay更好的解决方案是将异步管道的结果存储在变量中并使用它:

<some-component
  *ngIf="someColdObservable$ | async as result"
  [result]="result"
></some-component>