通过订阅它来读取可观察值的值

Read value of observable with subscribing to it

我有一个像

这样的可观察对象
imageOptions$: Observable<BoundImagesToProject[]> = this.imagesService
.getBoundImages({ projectId: this.projectId })
.pipe(map((images) => (images.data)));

我在模板中使用它

<div class="form-field input-group">
    <label for="image">Image</label>
    <mat-select id="image" class="select--full-width" placeholder="Image" formControlName="image">
      <mat-option *ngFor="let image of imageOptions$ | async" [value]="image.imageId">
        {{ image.name }}
      </mat-option>
    </mat-select>
    <mat-error *ngIf="createVmForm.get('image').getError('required') && createVmForm.get('image').dirty"
      >Field is required</mat-error
    >
  </div>

现在我想在 TS 文件中使用 imagesOptions$ observable,例如

this.imageChangeSubscription = this.createVmForm.get('image').valueChanges.subscribe((value) => {
  this.selectedImageVolumeSize = this.imagesOptions$ // get array value and match id and get the size.

如果它是一个数组,它会像

this.selectedImageVolumeSize = this.images.find((image) => image.imageId === value).size;

我想在不订阅 imageChangeSubscription 中可观察到的 imageOptions$ 的情况下执行此操作,以避免在侧面订阅中进行订阅,并且不在 TS 文件中使用额外的 属性

有什么办法吗?

您可以使用 switchMap() 来避免嵌套订阅。但是您应该更新 imagesOptions$ 以便它可以使用 shareReplay() 运算符与多个订阅者共享其最新值。

imageOptions$: Observable<BoundImagesToProject[]> = this.imagesService
  .getBoundImages({ projectId: this.projectId })
  .pipe(
    map(({data}) => data),
    shareReplay(1)
  );

然后在您的订阅中,获取 imageOptions$ 的最新值以找到您的尺码。

this.imageChangeSubscription = this.createVmForm
  .get('image').valueChanges
  .pipe(
    switchMap(value => this.imagesOptions$
      .pipe(
        map(images => images.find(({imageId}) => imageId===value ))
      )
    )
  ).subscribe();

我喜欢@Joshua McCarthy 提供的答案,但您根本不需要订阅,您可以获得“更清洁”(取决于消费者的角度)版本。

关于 shareReplay(1) 避免额外副作用(它们通常是 API 调用,导致不希望的网络消耗)的声明的荣誉。我强烈建议您将它应用于可观察到的图像选项。

然后我将继续创建另一个可观察对象:

import { combineLatest, shareReplay } from 'rxjs/operators'

@Component({...})
export class YourComponent {
    ...
    ...
    selectedImageVolumeSize$ = combineLatest([this.createVmForm['image'].valueChanges, this.imagesOptions$]).pipe(
        map(([selectedImageId, imageOptions] => imageOptions.find(item => item.id === selectedImageId)

    )

    constructor(...){}

}