Spec-Zone.ru › Angular

Дебаунсинг сигналов с debounced

ВАЖНО: debounced — экспериментальная функция. Вы можете попробовать её уже сейчас, но до выхода стабильной версии она может измениться.

Используйте debounced, чтобы отложить реакцию на значение сигнала до тех пор, пока оно не перестанет меняться. Функция возвращает Resource, значение которого отражает значение исходного сигнала после дебаунсинга.

import {debounced, resource, signal} from '@angular/core';

@Component({
  template: `
    <input (input)="query.set($event.target.value)" />

    @if (results.isLoading()) {
      <p>Searching…</p>
    }
    @for (item of results.value(); track item.id) {
      <li>{{ item.name }}</li>
    }
  `,
})
export class Search {
  query = signal('');

  debouncedQuery = debounced(this.query, 300);

  results = resource({
    params: () => this.debouncedQuery.value(),
    loader: ({params}) => fetchResults(params),
  });
}

debounced принимает исходный сигнал и длительность ожидания в миллисекундах. value() возвращаемого ресурса всегда содержит последнее установившееся значение, а status() сообщает, ожидается ли ещё новое значение.

Состояние во время дебаунсинга

Пока идёт отсчёт таймера дебаунсинга, status() имеет значение 'loading', а value() возвращает ранее разрешённое значение. Когда таймер истекает, ресурс переходит в состояние 'resolved'. Если исходный сигнал выбрасывает исключение, ресурс немедленно переходит в состояние 'error'; таймер не запускается.

Полный список состояний и их поведение при value() см. в разделе Состояние ресурса.

Пользовательская функция ожидания

Вместо длительности в миллисекундах можно передать функцию, возвращающую Promise<void>. Ресурс разрешается, когда разрешается промис. Если исходный сигнал изменится до разрешения промиса, Angular отбросит предыдущий промис и запустит новый.

debouncedQuery = debounced(query, (value, lastSnapshot) => {
  // Retry immediately after an error rather than making the user wait again.
  if (lastSnapshot.status === 'error') return;
  // Short queries get a longer delay—the user is likely still typing.
  const ms = value.length < 3 ? 500 : 200;
  return new Promise<void>((resolve) => setTimeout(resolve, ms));
});

Подробности см. в описании типа DebounceTimer в справочнике API.

Равенство

По умолчанию debounced использует Object.is для сравнения значений.

Если проверка идентичности по умолчанию слишком строгая, передайте пользовательскую функцию сравнения с помощью параметра equal:

debouncedFilter = debounced(filter, 200, {
  equal: (a, b) => a.category === b.category && a.minPrice === b.minPrice,
});

Контекст внедрения

debounced необходимо вызывать внутри контекста внедрения. Angular автоматически уничтожает ресурс с дебаунсингом и отменяет все ожидающие таймеры при уничтожении инжектора.

Чтобы использовать debounced вне контекста внедрения, передайте явный Injector через параметры:

@Service()
export class SearchService {
  private injector = inject(Injector);

  createDebouncedQuery(query: Signal<string>): Resource<string> {
    return debounced(query, 300, {injector: this.injector});
  }
}

Super-powered by Google ©2010–2025.
Code licensed under an MIT-style License. Documentation licensed under CC BY 4.0.
https://angular.dev/guide/signals/debounced

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API