gpt4 book ai didi

angular - 如何处理 Angular 延迟订阅

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

假设我有两个可观察对象供模板使用,一个包含数据,另一个作为加载指示器:

public readonly data$ = this.backend.get<Data>(...).pipe(
finalize((
{
this.isLoadingSubject$.next(1);
return () => this.isLoadingSubject$.next(-1);
})()
);
private readonly isLoadingSubject$ = new Subject<number>();
public readonly isLoading$ = isLoadingSubject$.pipe(
scan((acc, value) => acc + value, 0),
map((i) => i > 0),
);

关于 finalize 的解释: 当 data$ 的管道时,我正在使用 IIFE 开始加载被触发,并在完成时结束加载。我使用的是递增或递减的数字而不是 bool 值,因为可能有多个同时请求(许多可观察管道使用 isLoading$ 机制)。

在我的模板中,我是这样使用它的:

<ng-container *ngIf="data$ | async as data">
{{ data }}
<button [disabled]="isLoading$ | async">some button</button>
</ng-container>

问题是订阅isLoading$晚了:这个订阅只发生一次 data$已经发出,第一个.next(+1)被忽略,因为没有订阅者。

如何优雅地解决这个问题?

我尝试过但不喜欢的解决方法:

  • 订阅isLoading$立即让它变热 - 看起来很浪费,而且在阅读代码时,不清楚为什么要这样做。因此,如果仅从代码中不清楚它的用途,这似乎是一个糟糕的解决方法。
  • 重新排列模板,使 isLoading$在第一个<ng-container>然后 data$一秒钟内 <ng-container> - 但我必须处理 *ngIf加载时不呈现模板是 false ,所以我不得不把它包裹在一个对象中,这看起来又很浪费。而且,这会导致每次切换加载时都重新渲染所有内容,这是愚蠢的。
  • 查看了 publishReplay()运算符,但已弃用。
  • 同时包装 data$isLoading$在同一个对象里面 <ng-container> ,但是当加载指示器发生变化时整个模板都会重新呈现,这非常浪费 - 我只想禁用一个按钮。

最佳答案

我认为处理此问题的最简洁方法是使用您的“workaournd #4”;将两条数据放入单个对象(也称为 View 模型。Sander Elias 在 this video 中解释了这种模式):

const INITIAL_STATE = {
data : undefined,
isLoading : false,
};

@Component()
class MyComponent {
private isLoadingSubject$ = new Subject<number>();

private isLoading$ = isLoadingSubject$.pipe(
scan((acc, value) => acc + value, 0),
map(i => i > 0),
);

public vm$ = combineLatest({
data : this.getData() .pipe(startWith(INITIAL_STATE.data)),
isLoading : this.isLoading$ .pipe(startWith(INITIAL_STATE.isLoading))
});

private getData() {
this.isLoadingSubject.next(1);

return this.backend.get<Data>(...).pipe(
finalize(() => this.isLoadingSubject.next(-1))
);
}
}
<ng-container *ngIf="vm$ | async as vm">
{{ vm.data }}
<button [disabled]="vm.isLoading">some button</button>
</ng-container>

无需担心:

but then the whole template gets re-rendered whenever the loading indicator changes

此问题在 this part 中提到在前面提到的视频中。

虽然当组合 View 模型的任何部分发生变化时,确实会在组件上运行变化检测,但只有实际发生变化的元素才会被重新渲染;因此,如果只有 isLoading 属性发生变化,则只有按钮会在 UI 中更新。 data 的绑定(bind)不会受到影响,因为它没有改变。

关于angular - 如何处理 Angular 延迟订阅,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73141777/

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