angular - 在我订阅 observable 之前,异步管道不会收到值
问题描述
我遇到了一个奇怪的情况,当我订阅 observable 之前异步管道无法正常工作。资料来源:
组件视图:
<div *ngIf="loading$ | async" fxLayout="row" fxLayoutAlign="center">
<span class="spinner">Loading...</span>
</div>
<h1>{{data$ | async}}</h1>
零件:
@Component({
selector: './tm-fake',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './fake.component.html'
})
export class FakeComponent implements OnInit {
constructor(
private _fs: FakeService
) {}
loading$ = new BehaviorSubject<boolean>(false);
data$ = this._fs.data$.pipe(indicateUntilNULL(this.loading$));
ngOnInit(): void {
this._fs.requestData();
//this.data$.subscribe(e => {});
}
}
服务:
@Injectable()
export class FakeService {
requestData(): void {
timer(2000).pipe(map(e => "data")).subscribe(e => this._data.next(e));
}
private readonly _data = new BehaviorSubject<string>(null);
readonly data$ = this._data.asObservable();
}
操作员:
export function indicateUntilNULL<T>(indicator: BehaviorSubject<boolean>): (source: Observable<T>) => Observable<T> {
return source => source.pipe(
tap(e => indicator.next(!e))
);
}
我看到预期的data
2 秒后延迟,但在此延迟期间我没有看到微调器。但是,如果我取消注释该行this.data$.subscribe(e => {});
,它就会开始正常工作。而且我找不到原因。有任何想法吗?
注意:loading$
即使注释了这一行,也会发出正确的值。
解决方案
非常感谢@theMayer 和他的有用建议。我只是想添加文章,其中详细解释了问题。根据这篇文章,最优雅的解决方案是delay(0)
运算符:
export function indicateUntilNULL<T>(indicator: BehaviorSubject<boolean>): (source: Observable<T>) => Observable<T> {
return source => source.pipe(
delay(0),
tap(e => indicator.next(!e))
);
}
解决方案
好的,在查看您的代码后,我想我理解了这个问题。您没有看到通过DOM 中拾取true
的 observable 发出的更新值。loading$
这是您的代码所说的将发生的情况:
对象将被构造,行为主体
_data
将被初始化为空值。Angular 模板将呈现并通过更改检测。它将
false
为loading
value 和null
为data
. 装载微调器不会旋转。在更改检测周期的后期,
async
管道将触发true
要由 发出的值loading
。这是同步发生的;由于更改检测设置为OnPush
,我怀疑此更改将被错过,因为在设置值时已经有一个更改检测周期正在进行中(通常,这可能会被常规更改检测策略捕获并作为错误引发) .然后你
data
会在两秒延迟后发出。
请注意,当使用常规更改检测时,这种情况将导致ExpressionChangedAfterItHasBeenCheckedError
. 正确的方法是在变更检测周期之前确保组件的内部一致性,而不是在变更检测期间执行会触发进一步变更的事情。
快速的答案是最初将“加载”值设置为 true,因为代码在初始化时总是会尝试加载数据。
推荐阅读
- docker - 根据 http 请求启动/扩展容器化应用程序
- debian - Dovecot 从 postfix 压缩现有的 maildir 邮件
- kdb - kdb 中的垂直输出
- r - 根据闪亮应用中的 if 条件在同一动态 tabPanel 中导航
- here-api - 批量地理编码器是否已接近使用寿命?
- pytorch - 当训练损失减少时,验证损失增加和准确度保持为零的原因可能是什么?
- kivy - Kivy:RecycleView 未更新
- node.js - 具有数据库访问权限的单元测试 HTTP Post 请求
- php - 如何从 laravel 中的数组中获取多少条记录
- javascript - 打开第二个选项卡级别时,嵌套的 MaterialUI 选项卡会引发错误