시그널 값이 계속 변경되다가 멈췄을 때 반응하려면 debounced를 사용하면 됩니다.
이 함수를 실행하면 소스 시그널 값이 안정될 때 실행되는 Resource 시그널을 반환합니다.
import {Component, 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()도 오류를 던지며, 타이머는 실행되지 않습니다.
소스 시그널에서 더 이상 오류가 발생하지 않더라도 새로운 대기 시간이 끝날 때까지 리소스 시그널은 'error' 상태를 유지하며, 대기 시간이 끝나면 'resolved' 상태가 됩니다.
가능한 상태의 전체 목록과 value() 동작에 대해 더 알아보려면 Resource status 문서를 참고하세요.
커스텀 지연 함수
밀리초 단위로 타이머를 설정하는 대신, Promise<void>를 반환하는 함수를 사용할 수도 있습니다.
그러면 이 Promise가 종료될 때 리소스 시그널도 처리됩니다.
이 경우는 Promise가 안정화되기 전에 소스 시그널 값이 변경되면, Angular는 이전 Promise 동작을 폐기하고 새로운 Promise를 실행합니다.
debouncedQuery = debounced(query, (value, lastSnapshot) => {
// 에러가 발생하면 사용자가 더 기다리지 않도록 즉시 재시도합니다.
if (lastSnapshot.status === 'error') return;
// 짧은 쿼리는 사용자가 계속 입력하고 있을 수 있기 때문에 지연 시간을 길게 갖습니다.
const ms = value.length < 3 ? 500 : 200;
return new Promise<void>((resolve) => setTimeout(resolve, ms));
});
자세한 내용은 API 문서의 DebounceTimer 타입을 참고하세요.
동일값 확인
기본적으로 debounced는 Object.is를 사용해서 값을 비교합니다.
커스텀 동일성 판단 함수를 사용하려면 다음과 같이 equal 옵션을 지정하면 됩니다:
debouncedFilter = debounced(filter, 200, {
equal: (a, b) => a.category === b.category && a.minPrice === b.minPrice,
});
의존성 주입 컨텍스트
debounced는 반드시 의존성 주입 컨텍스트 안에서 실행되어야 합니다.
Angular는 인젝터가 종료되면 지연된 시그널을 자동으로 종료하며, 타이머도 만료시킵니다.
인젝션 주입 컨텍스트 밖에서 debounced를 실행하려면, 옵션으로 Injector를 명시적으로 전달해야 합니다: