如何在模板中为异步管道初始化一个可观察对象,试图模仿订阅中的分配?

How to initialized an observable for async pipe in the template trying to mimic an assignation in the subscription?

当前代码正在尝试使用异步管道方法而不是在订阅中使用赋值。但是如果延迟在服务中发生,初始值不会在模板中呈现,当数据准备好时,值会按预期呈现,我试图模仿使用此 this.title2.

组件:

title$: Observable<string> = of('Default Title'); // I am not sure if this assignation is right
title2 = 'Default Title 2';

constructor(private sampleService: SampleService) {}

// Load title has a delay in the response
this.title$ = this.sampleService.loadTitle();

this.sampleService.loadTitle().subscribe((title) => {
  this.title2 = title; // the assignation 
});

模板:

<h4>{{ title$ | async }}</h4>
<h4>{{ title2 }}</h4>

The sample is in this stackblitz

有几种方法可以解决此问题,但根据您提供的代码,您可以使用 switchMap 运算符,如下所示:

this.title$ = this.sampleService.loadTitle(); 更新为 this.title$.pipe(switchMap(() => this.sampleService.loadTitle()));

您目前正在做的是用不同的值覆盖 title$ 属性。 switchMap 使得每次第一个 observable 发出一个值时(在你的情况下,这只在你的 of('Default Title') 中发生一次)它会转身并创建另一个 observable,然后它会观察发出的值。

我想你想使用 startWith 做一个可观​​察的初始值。 尝试将代码更改为这个,它可以工作。

  this.title$ = this.sampleService
      .loadTitle()
      .pipe(startWith('Default Title'));

您可以使用 ng-container 订阅您的 observable 并重命名它,这样当数据准备好时,您可以简单地将它用作模板中的常规变量。 stackblitz

container.component.ts

export class ItemsComponent implements OnInit {
  @Input() name: string;
  items$: Observable<string[]>;
  title$: Observable<string>;

  constructor(private sampleService: SampleService) {}

  ngOnInit() {
    this.title$ = this.sampleService.loadTitle();
    this.items$ = this.sampleService.loadItems();
  }
}

container.component.html

<ng-container *ngIf="title$ | async as title">
  <h4>{{ title }}</h4>
</ng-container>

<ng-container *ngIf="items$ | async as items">
  <list *ngIf="items.length" [items]="items"></list>
</ng-container>

请记住,无论您在哪里使用异步一词,它都是新订阅。

如果您在模板中多次对同一个可观察对象使用异步管道,则您正在创建多个订阅。

如果您希望起始值与服务调用中的起始值不同,使用 startWith 运算符也是一个不错的选择。使用 startWith 的好地方是 formControl valueChanges observable,因为它没有起始值并且仅在值更改时触发。