( source: () => T, wait: NoInfer<DebounceTimer<T>>, options?: NoInfer<DebouncedOptions<T>>, )
| 34 | * @see [Debouncing signals with `debounced`](guide/signals/debounced) |
| 35 | */ |
| 36 | export function debounced<T>( |
| 37 | source: () => T, |
| 38 | wait: NoInfer<DebounceTimer<T>>, |
| 39 | options?: NoInfer<DebouncedOptions<T>>, |
| 40 | ): Resource<T> { |
| 41 | if (isInParamsFunction()) { |
| 42 | throw invalidResourceCreationInParams(); |
| 43 | } |
| 44 | if (ngDevMode && !options?.injector) { |
| 45 | assertInInjectionContext(debounced); |
| 46 | } |
| 47 | const injector = options?.injector ?? inject(Injector); |
| 48 | |
| 49 | let active: Promise<void> | void | undefined; |
| 50 | let pendingValue: T | undefined; |
| 51 | |
| 52 | injector.get(DestroyRef).onDestroy(() => { |
| 53 | active = undefined; |
| 54 | }); |
| 55 | |
| 56 | const state = linkedSignal< |
| 57 | {value: T; thrown: false} | {error: unknown; thrown: true}, |
| 58 | ResourceSnapshot<T> |
| 59 | >({ |
| 60 | source: () => { |
| 61 | try { |
| 62 | setInParamsFunction(true); |
| 63 | return {value: source(), thrown: false}; |
| 64 | } catch (err) { |
| 65 | rethrowFatalErrors(err); |
| 66 | return {error: err, thrown: true}; |
| 67 | } finally { |
| 68 | setInParamsFunction(false); |
| 69 | } |
| 70 | }, |
| 71 | computation: (res, previous) => { |
| 72 | // If we already have a state from the effect or a previous read, keep it! |
| 73 | // The effect is responsible for timing and state transitions. |
| 74 | if (previous !== undefined) { |
| 75 | return previous.value; |
| 76 | } |
| 77 | |
| 78 | // On the very first evaluation, determine the initial state synchronously. |
| 79 | if (res.thrown) { |
| 80 | return {status: 'error', error: res.error as Error}; |
| 81 | } |
| 82 | return {status: 'resolved', value: res.value}; |
| 83 | }, |
| 84 | }); |
| 85 | |
| 86 | effect( |
| 87 | () => { |
| 88 | // Enter error state if the source throws. |
| 89 | let value: T; |
| 90 | try { |
| 91 | setInParamsFunction(true); |
| 92 | value = source(); |
| 93 | } catch (err) { |
no test coverage detected
searching dependent graphs…