AsyncPipe 初始值只有在订阅不共享时才为 null
AsyncPipe initial value null only if subscription is not shared
给定一个看起来像这样的模板
<some-component
*ngIf="someColdObservable$ | async"
[result]="someColdObservable$ | async"
></some-component>
和一个如下所示的可观察对象:
someColdObservable$: this.store.pipe(
select(isAllowedToDoThis),
filter(Boolean),
flatMap(() => apiRequest())
);
someColdObservable$
被订阅了两次(正如预期的那样),这又发出了两次 api 调用(这显然是一种代码味道,但让我们暂时忽略它)。
在这种情况下 some-component
不包含任何空检查,如果 apiRequest
在 [=14= 之前未发出值,AsyncPipe
将 return 为空] 在模板中进行计算,导致 some-component
抛出 cannot access x of null
(因为此时 [result]
仍然为 null)see AsyncPipe
source for reference.
这是所有预期的行为(或至少在阅读源代码之后)但是,当我尝试通过将 shareReplay
添加到 someColdObservable$
来缓解发出两个请求的问题时,我还修复了[result]
在 apiRequest()
发出值之前为 null 的问题。这对我来说意义不大,因为我希望 AsyncPipe
仍然 return 和 null
_latestValue
在这里,cannot access x of null
错误未修复。但出于某种原因,添加 shareReplay
解决了上述两个问题。
这与 类似,但是,shareReplay
解决此问题的原因仍未得到解答。
有人能指出我在这里遗漏了什么以及为什么 AsyncPipe
在 apiRequest()
发出值之前不再 returns null
吗?
感谢任何指点和输入,谢谢!
第一种情况:
- 计算 ngIf 表达式。它订阅可观察对象并评估为 null。因此 [result] 表达式不会被计算,因为 ngIf 表达式是假的。
- observable 发射,ngIf 表达式变为真值。所以 [result] 表达式被评估。它自己的异步管道订阅发送另一个请求的冷可观察对象,并评估为 null,因此将其作为输入传递给组件。
第二种情况:
- 计算 ngIf 表达式。它订阅可观察对象并评估为 null。因此 [result] 表达式不会被计算,因为 ngIf 表达式是假的。
- observable 发射,ngIf 表达式变为真。所以 [result] 表达式被评估。它自己的异步管道订阅了热可观察对象,它会立即重播上次发出的内容,并且不再发送请求。因此表达式被评估为非空值,该值作为输入传递给组件。
比使用 shareReplay 更好的解决方案是将异步管道的结果存储在变量中并使用它:
<some-component
*ngIf="someColdObservable$ | async as result"
[result]="result"
></some-component>
给定一个看起来像这样的模板
<some-component
*ngIf="someColdObservable$ | async"
[result]="someColdObservable$ | async"
></some-component>
和一个如下所示的可观察对象:
someColdObservable$: this.store.pipe(
select(isAllowedToDoThis),
filter(Boolean),
flatMap(() => apiRequest())
);
someColdObservable$
被订阅了两次(正如预期的那样),这又发出了两次 api 调用(这显然是一种代码味道,但让我们暂时忽略它)。
在这种情况下 some-component
不包含任何空检查,如果 apiRequest
在 [=14= 之前未发出值,AsyncPipe
将 return 为空] 在模板中进行计算,导致 some-component
抛出 cannot access x of null
(因为此时 [result]
仍然为 null)see AsyncPipe
source for reference.
这是所有预期的行为(或至少在阅读源代码之后)但是,当我尝试通过将 shareReplay
添加到 someColdObservable$
来缓解发出两个请求的问题时,我还修复了[result]
在 apiRequest()
发出值之前为 null 的问题。这对我来说意义不大,因为我希望 AsyncPipe
仍然 return 和 null
_latestValue
在这里,cannot access x of null
错误未修复。但出于某种原因,添加 shareReplay
解决了上述两个问题。
这与 shareReplay
解决此问题的原因仍未得到解答。
有人能指出我在这里遗漏了什么以及为什么 AsyncPipe
在 apiRequest()
发出值之前不再 returns null
吗?
感谢任何指点和输入,谢谢!
第一种情况:
- 计算 ngIf 表达式。它订阅可观察对象并评估为 null。因此 [result] 表达式不会被计算,因为 ngIf 表达式是假的。
- observable 发射,ngIf 表达式变为真值。所以 [result] 表达式被评估。它自己的异步管道订阅发送另一个请求的冷可观察对象,并评估为 null,因此将其作为输入传递给组件。
第二种情况:
- 计算 ngIf 表达式。它订阅可观察对象并评估为 null。因此 [result] 表达式不会被计算,因为 ngIf 表达式是假的。
- observable 发射,ngIf 表达式变为真。所以 [result] 表达式被评估。它自己的异步管道订阅了热可观察对象,它会立即重播上次发出的内容,并且不再发送请求。因此表达式被评估为非空值,该值作为输入传递给组件。
比使用 shareReplay 更好的解决方案是将异步管道的结果存储在变量中并使用它:
<some-component
*ngIf="someColdObservable$ | async as result"
[result]="result"
></some-component>