Pipe through large list

2019-09-19 13:14发布

问题:

So I have a list of 2000+ employees and I need to filter through them. As I currently have it, it goes super slow and lags for 2 seconds. Everytime I type in a letter, it passes that list each time.

Any way to midigate the lag?

Update

This is some sample code:

<div style="margin-bottom:30px;" *ngIf="emulatedList">

   <input type="text" style="width:200px; background-color:#eeeeee;" name="searchText" [(ngModel)]="searchText" placeholder="Filter Dropdown List">

   <select style="background-color:#eeeeee;" [(ngModel)]="selected" placeholder="Emulate Person">
      <option *ngFor="let delegate of emulatedList | filter: searchText; trackBy: trackByName" [ngValue]="delegate.employeeid">
         {{delegate.employeename}}
      </option>
   </select>

   <span>
      <a (click)="addDelegate(selected)" style="background-color:#5B9C64; font-size:16px; color:#ffffff; padding:10px; margin-right:30px; border-radius: 10px;">Add Delegate</a>
   </span>

</div>

The component.ts file:

ngOnInit() {   
this.personsService.getEmulateList().subscribe(data => {
  setTimeout( () => {
    //console.log(data);
    this.emulatedList = data;
  }, 300);
});

回答1:

You can use a timeout, so that the code is not run until there have been no requests for x seconds

In the example below, although doFiltering is called in a loop 10 times, the console log statement is only printed once, exactly 1 second after the loop has finished

let handle; 

for(var i = 0; i < 10; i++) {
    doFiltering();
}

function doFiltering() {
    // Check if there is a reference to running timeout
    if (handle != null) {
        // Cancel it
        clearTimeout(handle);
    }
    // Start a timeout
    handle = setTimeout(() => {
        // Do you filtering in here
        console.log("Filtering now");
        handle = null;
    }, 1000);
}



回答2:

Rather than using pipe use rxjs/add/operator/debounceTime as:

HTML

<input [ngModel]='filterValue' (ngModelChange)='changed($event)' />

component.ts

filterValue: string;
modelChanged: Subject<string> = new Subject<string>();

constructor() {
    this.modelChanged
        .debounceTime(500) // you can change time
        .distinctUntilChanged() // emit only when value is different from previous value
        .subscribe(value => {
            this.filterValue = value;
            // perform filter
        });
}

changed(text: string) {
    this.modelChanged.next(text);
}


回答3:

You can use debounceTime if you are listening to the changing value. Not sure if you are using [(ngModel)] or a reactive form. It should be something like:

this.formCtrlSub = this.firstNameControl.valueChanges
  .debounceTime(1000)
  .subscribe(newValue => this.fetchNewResults());


回答4:

Instead of using the pipe, you can use a timer to wait for the user to stop typing and then filtering the results.

timer: any;

getList(searchText) {
 if (searchText.length >= 3) {
  clearTimeout(this.timer);
  this.timer = setTimeout(() => {
  // filter here
  }, 1100);
} 
else {
  this.list= [];
 }
}