Angular 2 добавляет функцию устранения дребезга непосредственно в канал

Я написал канал, который отфильтровывает массив объектов на основе заданного запроса. Это прекрасно работает, но я хотел бы добавить функцию устранения дребезга напрямую в этот канал, а не добавлять ее в событие keyup ввода, если это возможно.

Я искал решение, но не могу найти ничего, что соответствовало бы тому, что я ищу.

import {Pipe, PipeTransform} from '@angular/core';

@Pipe({
  name: 'filterBy'
})

export class FilterByPipe implements PipeTransform {

  transform(value: any, args: string[]): any[] {

    if (!args[0]) {
      return value;
    }
    else if (value) {

      return value.filter(item => {

        // TODO: Allow args[1] to be null, therefore searching in all object properties
        if ((typeof item[args[1]] === 'string' || item[args[1]] instanceof String) && (item[args[1]].toLowerCase().indexOf(args[0].toLowerCase()) !== -1)) {
          return true;
        }
      });
    }
  }
}

Любые идеи о том, как я могу реализовать это в этой трубе?


person Chrillewoodz    schedule 31.10.2016    source источник
comment
Где вы хотите применить debounce   -  person Bazinga    schedule 31.10.2016
comment
@PatrickJane Не знаю, куда ему идти.   -  person Chrillewoodz    schedule 31.10.2016
comment
Зачем нужен дебаунс?   -  person Bazinga    schedule 31.10.2016
comment
@PatrickJane Таким образом, он не фильтрует список из сотен элементов при каждом нажатии клавиши.   -  person Chrillewoodz    schedule 31.10.2016


Ответы (2)


Функции debounce или delay являются асинхронными, в этом случае вам нужно вернуть обещание или наблюдаемое из вашего канала и использовать асинхронный канал. Я создал простой пример, чтобы показать вам, как это сделать с наблюдаемым.

@Pipe({
    name: 'myfilter'
})

export class MyFilterPipe implements PipeTransform {
    transform(items, filterBy) {
      const filteredItems = items.filter(item => item.title.indexOf(filterBy.title) !== -1);
      return Observable.of(filteredItems).delay(1000);
    }
}


@Component({
  selector: 'my-app',
  template: `
    <div>
      <ul>
        <li *ngFor="let item of items | myfilter:filterBy | async">
         {{item.title}}
        </li>
      </ul>

      <input type="text" (input)="filter($event)">

    </div>
  `,
})
export class App {
  filterBy;
  constructor() {
    this.filterBy = {title: 'hello world'};
    this.items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];
  }

  filter($event) {
    this.filterBy = {title: $event.target.value}
  }
}

Плункер

person Bazinga    schedule 31.10.2016
comment
Разве это не просто добавляет задержку между вводом и выводом, а не устраняет дребезг (подождите x количество после последнего ввода перед обработкой)? - person 0xcaff; 24.11.2016
comment
Как мы можем оценить значение задержки? скажем, у меня есть 10 000 предметов (меньше или больше в моем случае) - person HDJEMAI; 28.12.2017
comment
Я только что протестировал это решение, но в моем случае оно не ускоряет фильтр, я не знаю, как решить эту проблему. - person HDJEMAI; 28.12.2017

Давайте представим сценарий, в котором текстовое поле выполняет задание «поиск по мере ввода». Чтобы записать значимый поисковый текст, компонент должен дождаться окончания набора текста.

Правильный способ установить время задержки для выполнения конвейера должен быть следующим (см. комментарии в коде):

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'searchFilter'
})
export class SearchFilterPipe implements PipeTransform {

  //-----
  //  1
  // ----
  //hold a timeout handle on class scope
  private timeoutHandle: number = -1;

  constructor(private dbLogger: DbLogService) {

  }

  transform(items: any, value?: any): any {

    if (!items) return [];

    //-----
    //  2
    // ----

    //clear time out handle on every pipe call
    //so that only handles created earlier than
    // 1000ms would execute
    window.clearTimeout(this.timeoutHandle);


    //-----
    // 3
    // ----

    //create time out handle on every pipe call
    this.timeoutHandle = window.setTimeout(() => {

      //-----
      // 4
      // ----

      //if there is no further typing,
      //then this timeout handle made the way to here:
      console.log("search triggered with value: " + value);
    }, 1000);

    return items.filter(it => it["name"].toLowerCase().indexOf(value.trim().toLowerCase()) !== -1);
  }

}
person Omer Gurarslan    schedule 17.05.2018