Skip to main content

Overview

The delay operator time-shifts each item emitted by the source Observable by a specified amount of time (in milliseconds) or until a specific Date occurs. The relative time intervals between values are preserved.

Signature

function delay<T>(
  due: number | Date,
  scheduler: SchedulerLike = asyncScheduler
): MonoTypeOperatorFunction<T>

Parameters

due
number | Date
required
The delay duration in milliseconds (as a number) or a Date until which the emission of the source items is delayed.
  • number: Delays each emission by this many milliseconds
  • Date: Delays the start of emissions until this date/time
scheduler
SchedulerLike
default:"asyncScheduler"
The scheduler to use for managing the timers that handle the time-shift for each item.

Returns

return
MonoTypeOperatorFunction<T>
A function that returns an Observable that delays the emissions of the source Observable by the specified timeout or Date.

Usage Examples

Delay by Milliseconds

Delay each click event by 1 second:
import { fromEvent, delay } from 'rxjs';

const clicks = fromEvent(document, 'click');
const delayedClicks = clicks.pipe(
  delay(1000)
);

delayedClicks.subscribe(x => console.log(x));
// Each click is logged 1 second after it occurs

Delay Until Date

Delay all emissions until a future date:
import { fromEvent, delay } from 'rxjs';

const clicks = fromEvent(document, 'click');
const date = new Date('March 15, 2050 12:00:00');

const delayedClicks = clicks.pipe(
  delay(date)
);

delayedClicks.subscribe(x => console.log(x));
// Clicks are only emitted after the specified date

Staggered Animation

Create a staggered animation effect:
import { from, delay, concatMap } from 'rxjs';

const items = ['First', 'Second', 'Third', 'Fourth'];

from(items).pipe(
  concatMap((item, index) => 
    of(item).pipe(delay(index * 500))
  )
).subscribe(item => {
  console.log(`${Date.now()}: ${item}`);
});

// Output (with increasing delays):
// 0ms: First
// 500ms: Second
// 1000ms: Third
// 1500ms: Fourth

Debounce Effect

Combine with other operators for complex timing:
import { fromEvent, map, delay, take } from 'rxjs';

const clicks$ = fromEvent(document, 'click');

clicks$.pipe(
  map(() => 'Click!'),
  delay(1000),
  take(1)
).subscribe(msg => {
  console.log(msg);
  // Only first click is processed, delayed by 1 second
});

How It Works

delay preserves the relative timing between emissions. If source emits at t=0ms, t=100ms, t=200ms, and you apply delay(1000), the result emits at t=1000ms, t=1100ms, t=1200ms.
When using a number delay:
  1. Each value from the source is queued
  2. A timer is started for that value
  3. After the delay period, the value is emitted
  4. Relative spacing between values is maintained
When using a Date delay:
  1. The operator waits until that date/time
  2. Then all subsequent values are emitted normally
  3. If the date is in the past, emissions start immediately

Common Use Cases

  1. Simulating Network Latency: Test how your app handles delayed responses
  2. Animation Timing: Create sequential animations with precise timing
  3. Rate Limiting: Add delays between API calls
  4. User Feedback: Delay showing loading indicators to avoid flashing
  5. Scheduled Actions: Start processing at a specific time

Comparison with Similar Operators

delay vs delayWhen: Use delay for fixed delays. Use delayWhen when the delay duration needs to be dynamic based on each emitted value.
OperatorDelay TypeUse Case
delayFixed duration or dateConsistent delays for all items
delayWhenDynamic per valueVariable delays based on value
debounceTimeResets on each emissionWait for pause in emissions
throttleTimeLimits rateEmit at most once per time period

Implementation Details

delay is implemented using delayWhen internally:
export function delay<T>(
  due: number | Date, 
  scheduler: SchedulerLike = asyncScheduler
): MonoTypeOperatorFunction<T> {
  const duration = timer(due, scheduler);
  return delayWhen(() => duration);
}
Error notifications from the source are NOT delayed and are passed through immediately. Use materialize and dematerialize if you need to delay error notifications.

Performance Considerations

  • Each delayed value creates a timer/subscription
  • For many rapid emissions, consider using bufferTime or auditTime instead
  • The scheduler parameter allows optimization for different contexts (browser animations, testing, etc.)
  • delayWhen - Delay based on another Observable
  • debounceTime - Delay and discard rapid emissions
  • throttleTime - Emit at most once per time period
  • timeout - Error if emissions are too slow
  • timer - Create Observable that emits after delay

See Also