函数在debounceTime

时间:2019-08-21 15:42:56

标签: angular rxjs

我有一个仅包含一个字段的反应式表单,当用户停止键入时,我想在控制台上打印该值。为此,当字段中的值更改时,我使用debounceTime()。 我读到了一些与How to use debounceTime in an angular component?Angular and debounce之类的debounceTime()的使用有关的问题,但是我的代码多次打印最新值,然后才检测到更改,并且经过了debounceTime函数中的时间

表单的输入字段为:

<input matInput formControlName="name" (keyup)="onInputChange()">

onInputChange函数中的代码是这样的:

this.userForm.get("name").valueChanges
          .pipe(
            debounceTime(500)
          )
          .subscribe(res => {
            console.log(res)
          });

如果输入为test,则控制台中的结果如下图所示:

enter image description here

怎么了?

2 个答案:

答案 0 :(得分:3)

您正在调用一个函数并在每次按键时订阅,您只需要订阅一次即可,而无需调用(keyup)函数,因为这将捕获对输入的任何更改。

似乎正在调用的函数可能导致创建四个订阅,因此在控制台中创建了四个条目。

<input matInput formControlName="name" (keyup)="onInputChange()">

应该是

<input matInput formControlName="name">

将此逻辑移至ngOnInit()中,以便在组件生命周期的早期创建订阅,并且仅创建一次。

然后您可以对该名称进行无引用复制,并在valuesChanged()块中进行比较,以确保该名称与发布前的原始名称不匹配。

userForm = this.formBuilder.group({
  name: ['']
)};
public originalName = '';

public ngOnInit(): void
{
    this.userService.getUserById(this.userId).subscribe(res => 
    {
      this.originalName = JSON.parse(JSON.stringify(res.name));
      this.userForm.controls['name'].setValue(res.name);

      this.userForm.get("name").valueChanges.pipe(debounceTime(500)).
      subscribe(res => 
      {
        if (res.name !== this.originalName) 
        {
          // logic to post to server
        }
      });
    });
}

还将建议您阅读有关销毁组件时如何处理订阅的信息,因为这将无法处理其自身,因此有很多可用资源。

答案 1 :(得分:1)

如其他答案中所述,没有keyup处理程序。只需听valueChanges。由于您要发出http请求,因此我们可以使用switchMap。还请记住退订valueChanges。如果用户仅键入空白,我们也可能希望过滤掉。所以我建议如下:

import { Subscription } from 'rxjs';
import { debounceTime, switchMap, filter } from 'rxjs/operators';

// ...

formSub = new Subscription();

ngOnInit() {
  this.formSub = this.userForm.get('name').valueChanges.pipe(
    debounceTime(500),
    filter(value => !!value.trim()),
    switchMap((value) => {
      // replace with your request
      return this.myService.postData(value)
    })
  // replace MyInterface with your model
  ).subscribe((data: MyInterface) => console.log(data))
}


ngOnDestroy() {
  this.formSub.unsubscribe();
}

然后以编程方式设置该值时出现问题。我们可以使用emitEvent: false,它不会导致valueChanges触发:

this.userForm.get('name').setValue('my name', { emitEvent: false })