在onChanges之前,异步管道似乎不会侦听Subject

问题描述 投票:0回答:2

零件:

@Component({
  templateUrl: 'widget.ng.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
})

  readonly purchases$ = of([]);

  readonly refunds$ = new Subject<Refund[]>();

  constructor() {
    //    this.refunds$.subscribe();
  }

  ngOnChanges() {
    this.refunds$.next([]);

模板:

<div #containerDiv>
  <collapsible-group>
    <div collapsible #collapsibleDiv>
      <mat-tab-group>
        <mat-tab>
          <ng-container *ngIf="purchases$ | async as purchases; else loading">
            <purchases-table
                [purchases]="purchases">
            </purchases-table>
          </ng-container>
        </mat-tab>

        <mat-tab>
          <ng-container *ngIf="refunds$ | async as refunds; else loading">
              <refunds-table [refunds]="refunds">
              </refunds-table>
          </ng-container>
        </mat-tab>
      </mat-tab-group>

      <!-- Loading State -->
      <ng-template #loading>
        Loading...
      </ng-template>
    </div>
  </collapsible-group>
</div>

在这段代码中:purchases按预期加载,而refunds则没有。但是,如果我取消注释构造函数中的行,refunds也将按预期工作。

异步管道似乎没有订阅主题,或者它可能无法在ngOnChanges之前订阅主题。这是正确的吗?

可能与OnPush有关?

angular typescript rxjs angular-material
2个回答
2
投票

使用行为主题,因为您可以将空数组作为初始值,并且您不必担心调用next时。

refunds$ = new BehaviorSubject<Refund[]>([]);

对主题的订阅只会获得订阅发生后发出的值,BehaviorSubjects在订阅时获取最后一个发射值。


0
投票

您一直是软件中两个合作缺陷的受害者。

首先是ngOnChanges()。当你想到时,它并没有完全被称为。只有在设置了@Input值时才会调用它,并且在第一次调用时,调用在调用ngOnInit()之前和模板的某些初始化完成之前进行。

另一个是Subject。因为它是RxJS中其他几个Subject的基类,所以你自然会认为它是你的默认类。不是这样!事实上,很少使用基础Subject,因为它根本没有缓冲能力。在编写Angular代码时,通常需要使用BehaviorSubject(当你有一个初始值时)或ReplaySubject(当你没有时)。

我用三个组成的Observables创建了一个Stackblitz app来说明你的选择。

你可以继续使用Subject,它的缺点是根本无法工作。

你可以使用ReplaySubjectBehaviorSubject并继续从ngOnChanges()触发它。这很有用......可能。 ngOnChanges()有点奇怪(在我看来),但它表现得系统化,你可以让它做你需要的。

我个人的偏好是使用ReplaySubjectBehaviorSubject并从@Input set()触发它。我认为这是可读性,效率和灵活性的良好结合。有关更多信息,请参阅here

© www.soinside.com 2019 - 2024. All rights reserved.