如何在Angular 6中的keyup事件中实现去抖时间

19 rxjs typescript angular

我创建了一个Angular应用程序,可以从API中搜索学生.它工作正常但每次更改输入值时都会调用API.我做过一项研究,我需要一些叫debounce的东西,但我不知道如何在我的应用程序中实现它.

App.component.html

    <div class="container">
  <h1 class="mt-5 mb-5 text-center">Student</h1>
<div class="form-group">
  <input  class="form-control form-control-lg" type="text" [(ngModel)]=q (keyup)=search() placeholder="Search student by id or firstname or lastname">
</div>
 <hr>
 <table class="table table-striped mt-5">
    <thead class="thead-dark">
      <tr>
        <th scope="col" class="text-center" style="width: 10%;">ID</th>
        <th scope="col" class="text-center" style="width: 30%;">Name</th>
       <th scope="col" style="width: 30%;">E-mail</th>
        <th scope="col" style="width: 30%;">Phone</th> 
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let result of results">
        <th scope="row">{{result.stu_id}}</th>
        <td>{{result.stu_fname}} {{result.stu_lname}}</td>
         <td>{{result.stu_email}}</td>
        <td>{{result.stu_phonenumber}}</td> 
      </tr>
    </tbody>
  </table>
</div>
Run Code Online (Sandbox Code Playgroud)

App.component.ts

import { Component} from '@angular/core';
import { Http,Response } from '@angular/http';
import { Subject, Observable } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent  {


  results;
  q = '';

  constructor(private http:Http) {


  }


  search() {
    this.http.get("https://www.example.com/search/?q="+this.q)
    .subscribe(
      (res:Response) => {
          const studentResult = res.json();
          console.log(studentResult);
          if(studentResult.success) {
            this.results = studentResult.data;
          } else {
            this.results = [];
          }
      }
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

截图 截图

我尝试了类似这样的东西,但它的错误 属性debounceTime在类型Subject <{}>上不存在

  mySubject = new Subject();
  constructor(private http:Http)  {
    this.mySubject
    .debounceTime(5000)
    .subscribe(val => {
      //do what you want
    });
  }
Run Code Online (Sandbox Code Playgroud)

而且这也行不通.类型'typeof Observable'上不存在属性'fromEvent'

    Observable.fromEvent<KeyboardEvent>(this.getNativeElement(this.term), 'keyup')
Run Code Online (Sandbox Code Playgroud)

那么,实现这个的正确方法是什么?

谢谢.

Bas*_*ani 13

在组件中你可以做这样的事情.创建RxJS Subject,在事件上search调用的方法中keyup,执行.next()此操作即可Subject创建.然后subscribengOnInit()debounce1秒,如下面的代码.

searchTextChanged = new Subject<string>();
constructor(private http:Http) {

}


ngOnInit(): void {
    this.subscription = this.searchTextChanged
        .debounceTime(1000)
        .distinctUntilChanged()
        .mergeMap(search => this.getValues())
        .subscribe(() => { });
}

getValues() {
    return this.http.get("https://www.example.com/search/?q="+this.q)
    .map(
      (res:Response) => {
          const studentResult = res.json();
          console.log(studentResult);
          if(studentResult.success) {
            this.results = studentResult.data;
          } else {
            this.results = [];
          }
      }
    )
}

search($event) {
    this.searchTextChanged.next($event.target.value);
}
Run Code Online (Sandbox Code Playgroud)

rxjs v6有几个重大变化,包括简化运营商的导入点.尝试安装rxjs-compat,在迁移代码之前添加这些导入路径.

从中导入必要的运算符RxJS.以下是RxJS 5.x

import { Subject } from "rxjs/Subject";
import "rxjs/add/operator/debounceTime";
import "rxjs/add/operator/distinctUntilChanged";
import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/mergeMap";
Run Code Online (Sandbox Code Playgroud)

  • 它仍然会出现错误**属性'debounceTime'在类型'Subject <string>'**上不存在于`.debounceTime(1000)`这是我的新代码.[链接](https://pastebin.com/N9NGywar) (2认同)

小智 6

对于任何在angular(和rxjs)的较新版本中遇到此问题的人。

新的Rxjs具有可管道运算符,可以像这样使用它们(来自已接受的答案代码)

ngOnInit() {
 this.subscription = this.searchTextChanged.pipe(
   debounceTime(1000),
   distinctUntilChanged(),
   mergeMap(search => this.getValues())
  ).subscribe((res) => {
    console.log(res);
  });
Run Code Online (Sandbox Code Playgroud)


Nad*_*lta 5

如果您正在使用角6和6 rxjs,试试这个:
注意在.pipe(debounceTime(1000))你的面前subscribe

import { debounceTime } from 'rxjs/operators';


search() {
    this.http.get("https://www.example.com/search/?q="+this.q)
    .pipe(debounceTime(1000))
    .subscribe(
      (res:Response) => {
          const studentResult = res.json();
          console.log(studentResult);
          if(studentResult.success) {
            this.results = studentResult.data;
          } else {
            this.results = [];
          }
      }
    )
  }
Run Code Online (Sandbox Code Playgroud)

  • 这不会以任何方式解决keyup事件 (4认同)
  • 不起作用,在每次键入事件时触发请求 (3认同)

Jay*_*ena 5

此外,您可以使用 angular formControls来绑定输入搜索字段

<input  class="form-control form-control-lg" 
type="text" [formControl]="searchField"
placeholder="Search student by id or firstname or lastname">
Run Code Online (Sandbox Code Playgroud)

并在我们的 searchField 上使用valueChanges observable 来响应App.component.ts文件中 out 搜索字段的更改。

searchField: FormControl; 

ngOnInit() {
    this.searchField.valueChanges
      .debounceTime(5000) 
      .subscribe(term => {
    // call your service endpoint.
      });
}
Run Code Online (Sandbox Code Playgroud)

可选地,您可以使用distinctUntilChanged(如果发布的值与前一个不同,则仅发布到其输出流)

searchField: FormControl; 

ngOnInit() {
    this.searchField.valueChanges
      .debounceTime(5000) 
     .distinctUntilChanged()
     .subscribe(term => {
            // call your service endpoint.
      });
}
Run Code Online (Sandbox Code Playgroud)