Throttled

Creates a throttled signal that limits how often the value can update.

Loading demo...

Usage

Writable signal

Creates a new writable signal where both set() and update() calls are throttled:

angular-ts
import { Component, effect } from '@angular/core';
import { throttled } from '@signality/core';

@Component({
  template: `
    <input [(ngModel)]="value" />
  `,
})
export class ThrottledInput {
  readonly value = throttled('', 100); 

  constructor() {
    effect(() => {
      console.log('Throttled:', this.value());
    });
  }
}

Computed signal

Wraps an existing signal with throttle behavior:

angular-ts
import { Component, signal, effect } from '@angular/core';
import { throttled } from '@signality/core';

@Component({ /* ... */ })
export class ThrottledInput {
  readonly rawValue = signal(0);
  readonly throttledValue = throttled(this.rawValue, 200); 

  constructor() {
    effect(() => {
      console.log('Throttled:', this.throttledValue());
    });
  }
}

Debounced vs Throttled

BehaviorDebouncedThrottled
UpdatesAfter inactivityAt regular intervals
Use caseWait for user to stopLimit update frequency
ExampleSearch inputScroll position

Parameters

ParameterTypeDescription
sourceSignal<T> or TSource signal to throttle, or initial value for writable signal
timeMsMaybeSignal<number>Throttle interval in milliseconds
optionsThrottledOptions<T>Optional configuration (see Options below)

Options

The ThrottledOptions<T> extends CreateSignalOptions<T> and WithInjector:

OptionTypeDescription
equalValueEqualityFn<T>Custom equality function (see more)
debugNamestringDebug name for the signal (development only)
injectorInjectorOptional injector for DI context

Return Value

  • When passed a signal → returns Signal<T> (readonly)
  • When passed a value → returns WritableSignal<T>

Examples

Scroll position tracking

angular-ts
import { Component, signal, effect } from '@angular/core';
import { throttled, listener } from '@signality/core';

@Component({
  template: `<p>Scroll Y: {{ scrollY() }}px</p>`,
})
export class ScrollTracker {
  readonly scrollY = throttled(0, 50);

  constructor() {
    listener(window, 'scroll', () => {
      this.scrollY.set(window.scrollY);
    });

    effect(() => {
      // Updates at most every 50ms during scroll
      console.log('Scroll position:', this.scrollY());
    });
  }
}

Mouse position

angular-ts
import { Component, signal, computed } from '@angular/core';
import { throttled, listener } from '@signality/core';

@Component({
  template: `
    <div class="tracker">
      Mouse: {{ position().x }}, {{ position().y }}
    </div>
  `,
})
export class MouseTracker {
  readonly position = throttled({ x: 0, y: 0 }, 16); // ~60fps

  constructor() {
    listener(document, 'mousemove', (e: MouseEvent) => {
      this.position.set({ x: e.clientX, y: e.clientY });
    });
  }
}

SSR Compatibility

Throttle timers are not started on the server — the initial value is returned immediately.

Type Definitions

typescript
type ThrottledOptions<T> = CreateSignalOptions<T> & WithInjector;

// Overload 1: Computed from signal (readonly)
function throttled<S extends Signal<any>>(
  source: S,
  timeMs: MaybeSignal<number>,
  options?: ThrottledOptions<SignalValue<S>>
): Signal<SignalValue<S>>;

// Overload 2: Writable signal from value
function throttled<V>(
  value: V,
  timeMs: MaybeSignal<number>,
  options?: ThrottledOptions<V>
): WritableSignal<V>;
Edit this page on GitHub Last updated: Mar 19, 2026, 23:28:23