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

如何在Angular 6中的keyup事件中实现去盎司时间,angular,typescript,rxjs,Angular,Typescript,Rxjs,我创建了一个Angular应用程序,可以从API搜索学生。它工作正常,但每次更改输入值时都会调用API。我做了一项研究,我需要一种叫做debounce的东西,但我不知道如何在我的应用程序中实现它 App.component.html <div class="container"> <h1 class="mt-5 mb-5 text-center">Student</h1> <div class="form-group"> <i

我创建了一个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>
屏幕截图

我试过这样的方法,但都是错误的 类型主题上不存在属性debounceTime

这也不管用属性“fromEvent”在类型“typeof Observable”上不存在。

    Observable.fromEvent<KeyboardEvent>(this.getNativeElement(this.term), 'keyup')
Observable.fromEvent(this.getNativeElement(this.term),'keyup')
那么,正确的方法是什么呢


谢谢。

在组件中,您可以执行类似的操作。创建RxJS
Subject
,在
search
方法中(该方法在
keyup
事件中调用),对您创建的
Subject执行
.next()
。然后
ngOnInit()
中的
subscribe
debounce
持续1秒,如下代码所示

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);
}

如果您使用的是angular 6和rxjs 6,请尝试以下操作:
请注意
订阅之前的
.pipe(debounceTime(1000))

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 = [];
          }
      }
    )
  }

此外,还可以使用angularformControls绑定输入搜索字段

<input  class="form-control form-control-lg" 
type="text" [formControl]="searchField"
placeholder="Search student by id or firstname or lastname">
(可选)您可以使用distinctUntilChanged(仅当发布的值不同于上一个值时,才会发布到其输出流)


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

新的Rxjs具有管道操作符,它们可以像这样使用(根据公认的答案代码)

user.component.html

   <input type="text" #userNameRef class="form-control"  name="userName" >  <!-- template-driven -->
 <form [formGroup]="regiForm"> 
      email: <input formControlName="emailId"> <!-- formControl -->
    </form>
*注意:确保您的输入元素不在ngIf块中。

演示

教程来源

使用模板变量

<input type="text" #movieSearchInput class="form-control" placeholder="Type any movie name" />

    ...
    ...    
        fromEvent(this.movieSearchInput.nativeElement, 'keyup').pipe(
        // get value
        map((event: any) => {
            return event.target.value;
        })
        // if character length greater then 2
        ,filter(res => res.length > 2)
        // Time in milliseconds between key events
        ,debounceTime(1000)        
        // If previous query is diffent from current   
        ,distinctUntilChanged()
        // subscription for response
        ).subscribe((text: string) => {
            this.isSearching = true;
            this.searchGetCall(text).subscribe((res)=>{
            console.log('res',res);
            this.isSearching = false;
            this.apiResponse = res;
            },(err)=>{
            this.isSearching = false;
            console.log('error',err);
            });
        });
    ...
    ...

...
...    
fromEvent(this.movieSearchInput.nativeElement,'keyup').pipe(
//获得价值
地图((事件:任意)=>{
返回event.target.value;
})
//如果字符长度大于2
,过滤器(res=>res.length>2)
//关键事件之间的时间(毫秒)
,去BounceTime(1000)
//如果上一个查询与当前查询不同
,distinctUntilChanged()
//订阅以获取响应
).订阅((文本:字符串)=>{
this.isSearching=true;
this.searchGetCall(text).subscribe((res)=>{
console.log('res',res);
this.isSearching=false;
this.apiResponse=res;
},(错误)=>{
this.isSearching=false;
console.log('error',err);
});
});
...
...

像这样使用,不带RXJS

它可能会在每次键控时调用“search()”函数本身,但不会每次都调用函数的内部内容(如http connect)。非常简单的解决方案

export class MyComponent implements OnInit {

  debounce:any;

  constructor(){}
  
  search(){
    clearTimeout(this.debounce);
    this.debounce = setTimeout(function(){
      // Your Http Function..
    },500); // Debounce time is set to 0.5s
  }
}

仍然存在一个错误属性“debounceTime”在
的类型“Subject”上不存在。debounceTime(1000)
这是我的新代码@mongkonsrisin,rxjs v6有几个突破性的更改,包括简化操作员的导入点。尝试安装
rxjs compat
,这将添加回那些导入路径,直到代码被迁移。安装rxjs compat后,该错误消失,但在
this处有另一个错误。getValues(search)
应为0个参数,但得到1@mongkonsrisin,很抱歉,在
ngOnInit
this.getValues(搜索)中
应该是
this.getValues()
,因为它不需要任何参数。我已经更新了answerIt's still error参数的类型'(search:string)=>void'不可分配给参数的类型'(value:string,index:number)=>ObservableInput)。这在任何情况下都不会解决keyup事件way@Logus在对问题的描述中,这家伙问他需要实现一个叫做去BounceTime的东西,但他不知道如何实现。@NadhirFalta,这个标题实际上提到他想在keyup事件中实现去BounceTime。@Logus问题描述中是这样说的:“我做了一项研究,我需要一种叫做debounce的东西,但我不知道如何在我的应用程序中实现它。”这个实现并不完整,但这是答案
.pipe(debounceTime(1000))中的关键部分
结合已接受的答案,使用RxJs解决了我的issueCheck Angular Input DebounceTime示例。首先,在我的ngOnInit()方法中未定义@ViewChild。因此,我在ngAfterViewInit()中添加了整个fromEvent。但是,当我键入输入时,在第一个键控中,我的订阅事件仅在第一个类型中调用,而在我再次键入时不会调用。
searchField: FormControl; 

ngOnInit() {
    this.searchField.valueChanges
      .debounceTime(5000) 
      .subscribe(term => {
    // call your service endpoint.
      });
}
searchField: FormControl; 

ngOnInit() {
    this.searchField.valueChanges
      .debounceTime(5000) 
     .distinctUntilChanged()
     .subscribe(term => {
            // call your service endpoint.
      });
}
ngOnInit() {
 this.subscription = this.searchTextChanged.pipe(
   debounceTime(1000),
   distinctUntilChanged(),
   mergeMap(search => this.getValues())
  ).subscribe((res) => {
    console.log(res);
  });
   <input type="text" #userNameRef class="form-control"  name="userName" >  <!-- template-driven -->
 <form [formGroup]="regiForm"> 
      email: <input formControlName="emailId"> <!-- formControl -->
    </form>
       import { fromEvent } from 'rxjs';
       import { switchMap,debounceTime, map } from 'rxjs/operators';


        @Component({
          selector: 'app-user',
          templateUrl: './user.component.html',
          styleUrls: ['./user.component.css']
        })
        export class UserComponent implements OnInit {

          constructor(private userService : UserService) { }


             @ViewChild('userNameRef') userNameRef : ElementRef;

             emailId = new FormControl(); 
   regiForm: FormGroup = this.formBuilder.group({
      emailId: this.bookId
   });   

             ngOnInit() {

                    fromEvent(this.userNameRef.nativeElement,"keyup").pipe(
                    debounceTime(3000),
                    map((userName : any) =>userName.target.value )
                  ).subscribe(res =>{
                    console.log("User Name is :"+ res);

                  } );
    //--------------For HTTP Call------------------

                  fromEvent(this.userNameRef.nativeElement,"keyup").pipe(
                    debounceTime(3000),
                    switchMap((userName : any) =>{
                   return this.userService.search(userName.target.value)
                 })
                  ).subscribe(res =>{
                    console.log("User Name is :"+ res);

                  } );



----------
                // For formControl 

                  this.emailId.valueChanges.pipe(
                  debounceTime(3000),
                  switchMap(emailid => {
                         console.log(emailid);
                        return this.userService.search(emailid);
                        })
                         ).subscribe(res => {
                               console.log(res);
                                    });


            }
<input type="text" #movieSearchInput class="form-control" placeholder="Type any movie name" />

    ...
    ...    
        fromEvent(this.movieSearchInput.nativeElement, 'keyup').pipe(
        // get value
        map((event: any) => {
            return event.target.value;
        })
        // if character length greater then 2
        ,filter(res => res.length > 2)
        // Time in milliseconds between key events
        ,debounceTime(1000)        
        // If previous query is diffent from current   
        ,distinctUntilChanged()
        // subscription for response
        ).subscribe((text: string) => {
            this.isSearching = true;
            this.searchGetCall(text).subscribe((res)=>{
            console.log('res',res);
            this.isSearching = false;
            this.apiResponse = res;
            },(err)=>{
            this.isSearching = false;
            console.log('error',err);
            });
        });
    ...
    ...
export class MyComponent implements OnInit {

  debounce:any;

  constructor(){}
  
  search(){
    clearTimeout(this.debounce);
    this.debounce = setTimeout(function(){
      // Your Http Function..
    },500); // Debounce time is set to 0.5s
  }
}