gpt4 book ai didi

angular - 在我订阅可观察对象之前,异步管道不会收到值

转载 作者:行者123 更新时间:2023-12-05 06:25:59 24 4
gpt4 key购买 nike

我遇到过一个奇怪的情况,异步管道在我订阅可观察对象之前无法正常工作。资料来源:

组件 View :

<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))
);
}

我按预期在延迟 2 秒后看到了 data,但在此延迟期间我没有看到微调器。但是如果我取消注释行 this.data$.subscribe(e => {}); 它开始工作正常。我找不到原因。有什么想法吗?

注意:即使此行被注释,loading$ 也会发出正确的值。

解决方案

非常感谢@theMayer 和他的有用建议。我只想添加 article ,其中详细解释了问题。根据这篇文章,最优雅的解决方案是 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 中拾取的 loading$ observable 发出的 true 的更新值。

这是您的代码所说的将发生的事情:

  1. 将构造对象,并将行为主体 _data 初始化为空值。

  2. Angular 模板将呈现并进行变更检测。它将为 loading 值选择 false,为 data 选择 null。加载旋转器不会旋转。

  3. 稍后在变更检测周期中,async 管道将触发 true 值由 loading 发出。这是同步发生的;由于更改检测设置为 OnPush,我怀疑此更改将被遗漏,因为在设置该值时已经有一个正在进行的更改检测周期(通常,这可能会被常规更改捕获检测策略并作为错误引发)。

  4. 然后您的数据会在两秒延迟后发出。

请注意,当使用常规更改检测时,这种情况将导致 ExpressionChangedAfterItHasBeenCheckedError。正确的方法是在变更检测周期之前确保组件的内部一致性,而不是在变更检测期间做一些会触发进一步变更的事情。

快速的答案是最初将“loading”值设置为 true,因为代码在初始化时总是会尝试加载数据。

关于angular - 在我订阅可观察对象之前,异步管道不会收到值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56545558/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com