为什么当没有可观察对象发出值时我的 RxJS 合并订阅会触发?

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

我有这样的 Angular 代码,它监听多个字段的更改,然后在其中任何一个字段发生更改时保存更改。问题是,即使控制台没有记录任何内容,故事也会被保存,这意味着不应该触发任何可观察对象。为什么保存被调用以及如何调试它?

    merge([
        this.form.get('storyName').valueChanges.pipe(tap(x => console.log('storyName', x))),
        this.form.get('storyTypeId').valueChanges.pipe(tap(x => console.log('storyTypeId', x))),
        this.form.get('backlogId').valueChanges.pipe(tap(x => console.log('backlogId', x))),
        this.form.get('ownerUserId').valueChanges.pipe(tap(x => console.log('ownerUserId', x))),
        this.form.get('points').valueChanges.pipe(tap(x => console.log('points', x))),
        this.form.get('tags').valueChanges.pipe(tap(x => console.log('tags', x))),
      ]).pipe(
        debounceTime(300),
      ).subscribe(async () => {
        try {
          await this.saveStory();
        } finally {
          this.isSavingStory = false;
        }
      });
angular rxjs
2个回答
1
投票

尝试删除数组,而只需将

valueChanges
作为参数传递给
merge

...
merge(
  this.form
    .get('input')!
    .valueChanges.pipe(tap((x) => console.log('input', x))),
  this.form
    .get('select')!
    .valueChanges.pipe(tap((x) => console.log('select', x))),
  this.form
    .get('textarea')!
    .valueChanges.pipe(tap((x) => console.log('textarea', x)))
)
...

完整代码:

TS:

import { Component } from '@angular/core';
import { MatSelectModule } from '@angular/material/select';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { FormGroup, ReactiveFormsModule, FormControl } from '@angular/forms';
import { tap, debounceTime } from 'rxjs/operators';
import { merge } from 'rxjs';

/** @title Simple form field */
@Component({
  selector: 'form-field-overview-example',
  templateUrl: 'form-field-overview-example.html',
  styleUrl: 'form-field-overview-example.css',
  standalone: true,
  imports: [
    MatFormFieldModule,
    MatInputModule,
    MatSelectModule,
    ReactiveFormsModule,
  ],
})
export class FormFieldOverviewExample {
  isSavingStory = false;
  form = new FormGroup({
    input: new FormControl(''),
    select: new FormControl(''),
    textarea: new FormControl(''),
  });

  ngOnInit() {
    merge(
      this.form
        .get('input')!
        .valueChanges.pipe(tap((x) => console.log('input', x))),
      this.form
        .get('select')!
        .valueChanges.pipe(tap((x) => console.log('select', x))),
      this.form
        .get('textarea')!
        .valueChanges.pipe(tap((x) => console.log('textarea', x)))
    )
      .pipe(debounceTime(300))
      .subscribe(() => {
        try {
          console.log('saveStory');
        } finally {
          this.isSavingStory = false;
        }
      });
  }
}

HTML

<form [formGroup]="form">   <mat-form-field>
    <mat-label>Input</mat-label>
    <input matInput formControlName="input" />   </mat-form-field>   <mat-form-field>
    <mat-label>Select</mat-label>
    <mat-select formControlName="select">
      <mat-option value="one">First option</mat-option>
      <mat-option value="two">Second option</mat-option>
    </mat-select>   </mat-form-field>   <mat-form-field>
    <mat-label>Textarea</mat-label>
    <textarea matInput formControlName="textarea"></textarea>   </mat-form-field> </form>

Stackblitz 演示


0
投票

如果认为代码中唯一的问题是您将数组传递给合并运算符,而不是一个接一个地声明内部可观察值:

我相信这应该有效:

merge(
  this.form.get('storyName').valueChanges.pipe(tap(x => console.log('storyName', x))),
  this.form.get('storyTypeId').valueChanges.pipe(tap(x => console.log('storyTypeId', x))),
  this.form.get('backlogId').valueChanges.pipe(tap(x => console.log('backlogId', x))),
  this.form.get('ownerUserId').valueChanges.pipe(tap(x => console.log('ownerUserId', x))),
  this.form.get('points').valueChanges.pipe(tap(x => console.log('points', x))),
  this.form.get('tags').valueChanges.pipe(tap(x => console.log('tags', x))),
).pipe(
  debounceTime(300),
).subscribe(async () => {
  try {
    await this.saveStory();
  } finally {
    this.isSavingStory = false;
  }
});

我还希望您给您一个提示,当尝试按名称访问包含的表单控件时,您可以使用 FormGroup 中的控件属性来获得良好的自动完成功能:

merge(
  this.form.controls.storyName.valueChanges.pipe(tap(x => console.log('storyName', x))),
  this.form.controls.storyTypeId.valueChanges.pipe(tap(x => console.log('storyTypeId', x))),
  this.form.controls.backlogId.valueChanges.pipe(tap(x => console.log('backlogId', x))),
  this.form.controls.ownerUserId.valueChanges.pipe(tap(x => console.log('ownerUserId', x))),
  this.form.controls.points.valueChanges.pipe(tap(x => console.log('points', x))),
  this.form.controls.tags.valueChanges.pipe(tap(x => console.log('tags', x))),
).pipe(
  debounceTime(300),
).subscribe(async () => {
  try {
    await this.saveStory();
  } finally {
    this.isSavingStory = false;
  }
});

希望这有帮助!

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