0

我是 Angular2+ 和 RxJs 的新手,所以如果我问一些明显的问题,我很抱歉。

功能性

当数据刚刚开始加载、startAction发出、isLoaded转动false并显示微调器时。

一旦数据被加载,endAction被发射, isLoaded 被设置为true。微调器被隐藏起来,并描绘了主要数据。

一旦用户单击另一个按钮,就会加载另一数量的数据。startAction再次发出,微调器将再次显示,直到数据加载。

我有的

在组件中:

this.startAction.subscribe(() => {this.isLoaded = false;});
this.endAction.subscribe(() => {this.isLoaded = true;});

在模板中:

<ng-container *ngIf="isLoaded; else loading">
  ...data...
</ng-container>

<ng-template #loading>
  <mat-spinner></mat-spinner>
</ng-template>

我需要的

一切都很好,但我需要重新设计这种方法,使其更具反应性。我必须摆脱订阅并isLoaded变成可观察的才能通过async模板中的管道使用它。

我试过的

在组件中:

isStartLoading = this.startAction.pipe(mapTo(false));
isEndLoading = this.endAction.pipe(mapTo(true));
isLoaded = combineLatest([this.isStartLoading, this.isEndLoading])
  .pipe(takeLast(1)); // does not emit
  //.pipe(last()); // does not emit
  //.pipe(take(1)); // emits only once

在模板中:

<ng-container *ngIf="isLoaded | async; else loading">
...

我的解释

根据我的理解,必须在andtakeLast(1)之间发出最后一个动作。所以当发生时,应该发出一个 observable over ,when -一个 observable over 。isStartLoadingisEndLoadingstartActiontakeLast(1)falseendActiontrue

出于某种原因,我只看到了初始微调器,并且没有描述结果数据。看起来我对combineLatest+takeLast应该如何协同工作有错误的理解。

当我tap(console.log)takeLast(1)/之后添加时last(),我看到它永远不会发出。但是当用 替换它时take(1),它预计只会发出一次。所以我看到了微调器,然后是数据,然后在单击另一个按钮后 - 新加载的数据有延迟且没有微调器,因为我们只采用第一个。

任何帮助表示赞赏!

4

2 回答 2

0

我会在 redux reducer 中创建一个名为isLoading的新属性,默认情况下将其设置为 false,然后将 start 和 end 操作分别更改为 true、false。

然后在你的组件中你可以这样说,我假设你的减速器被称为“布局”:

ngOnInit() {

this.isLoading$ = this.store.pipe(select('layout'), pluck('isLoading'), distinctUntilChanged<boolean>());

}

在 html 中你说:

<div *ngIf="isLoading$ | async"><div/> else notloading stuff.
于 2020-02-03T10:03:37.987 回答
0

您的初始解决方案非常接近,但combineLatest仅在两个可观察对象都已发出然后继续合并来自可观察对象的最新排放时才发出。

您可以使用 来实现您正在寻找的东西merge,因为它会为每个 observable 发出一个值。

const isStartLoading = this.startAction
    .pipe(mapTo(false));

const isEndLoading = this.endAction
    .pipe(mapTo(true));

const isLoaded = merge(this.isStartLoading, this.isEndLoading);

然后你可以异步管道 isLoaded 值。

<ng-container *ngIf="isLoaded | async; else loading">

请注意,发射的顺序与 没有关系merge,如果在你isEndLoading之前发射isStartLoading就会有问题。

concat如果您不能保证可观察对象按顺序发出时发出的顺序,则可能是一个更好的选择。

const isLoaded = concat(this.isStartLoading, this.isEndLoading);

这是两个示例的StackBlitz

于 2020-02-04T22:50:26.210 回答