How to Implement Sleep Function in TypeScript?

When working on asynchronous JavaScript applications with TypeScript, I often need to introduce deliberate delays in code execution. Whether it’s for rate limiting API calls, creating animations, or simulating network latency during testing, a sleep function becomes indispensable.

In this article, I’ll share multiple ways to implement a sleep function in TypeScript based on my experience. These methods will help you pause code execution elegantly without blocking the main thread.

What is a Sleep Function?

A sleep function pauses the execution of code for a specified amount of time before continuing. Unlike languages like Python or C# that have built-in sleep functions, TypeScript doesn’t have one out of the box.

However, we can easily create our own sleep function using JavaScript’s asynchronous capabilities. Let’s explore several approaches.

Check out: Function Overloading in TypeScript

Method 1: Using Promises with setTimeout in TypeScript

The most common and reliable approach is to create a Promise-based sleep function:

function sleep(ms: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
  console.log("Starting process...");
  await sleep(2000);
  console.log("Waited 2 seconds");
  console.log("Continuing after delay");
}

demo();

Output:

Sleep function in TypeScript

This approach wraps JavaScript’s setTimeout in a Promise, allowing you to use it with async/await syntax. It’s clean, readable, and follows modern JavaScript practices.

Check out: Spread Operator in TypeScript

Method 2: Using a One-liner Arrow Function in TypeScript

If you prefer a more concise syntax, you can implement the sleep function as an arrow function:

const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

// Usage example
async function processTransactions() {
  console.log("Processing transaction 1");
  await sleep(1000);
  console.log("Processing transaction 2");
  await sleep(1000);
  console.log("All transactions completed");
}

processTransactions();

Output:

TypeScript Sleep function

This one-liner achieves the same result as Method 1 but with less code. I often use this approach in my projects for its simplicity.

Check out: TypeScript Type Narrowing

Method 3: Adding Return Value Support in TypeScript

Sometimes, you might want your sleep function to return a value after the delay. Here’s how to implement that:

function sleepWithValue<T>(ms: number, value: T): Promise<T> {
  return new Promise(resolve => setTimeout(() => resolve(value), ms));
}

// Usage example
async function fetchUserData() {
  console.log("Fetching user data...");

  // Simulate API call with a delay that returns user data
  const userData = await sleepWithValue(2000, {
    id: 123,
    name: "John Smith",
    location: "New York",
    subscription: "Premium"
  });

  console.log("User data received:", userData);
  return userData;
}

fetchUserData();

Output:

API Call using Sleep function in TypeScript

This generic implementation allows you to specify the return type and value, making it useful for mocking API responses during development or testing.

Check out: TypeScript Constructor Overloading

Method 4: Creating a Sleep Utility Class in TypeScript

For larger applications, I sometimes prefer organizing utility functions into classes:

class TimerUtils {
  /**
   * Pauses execution for the specified number of milliseconds
   * @param ms Milliseconds to wait
   */
  static sleep(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * Executes a callback after the specified delay
   * @param ms Milliseconds to wait
   * @param callback Function to execute after delay
   */
  static delayedExecution(ms: number, callback: () => void): void {
    setTimeout(callback, ms);
  }

  /**
   * Returns a value after the specified delay
   * @param ms Milliseconds to wait
   * @param value Value to return
   */
  static sleepWithValue<T>(ms: number, value: T): Promise<T> {
    return new Promise(resolve => setTimeout(() => resolve(value), ms));
  }
}

// Usage example
async function processDataImport() {
  console.log("Starting data import...");

  // Wait for 1 second
  await TimerUtils.sleep(1000);
  console.log("Processing batch 1");

  // Execute a callback after 1.5 seconds
  TimerUtils.delayedExecution(1500, () => {
    console.log("Callback executed");
  });

  // Wait and return a value
  const result = await TimerUtils.sleepWithValue(2000, {
    status: "success",
    recordsProcessed: 1250,
    errors: 0
  });

  console.log("Import completed:", result);
}

processDataImport();

Output:

Sleep function Utility Class in TypeScript

This approach provides a more organized and extensible way to handle timing-related utilities in larger applications.

Check out: Set Default Values in TypeScript Interfaces

Real-World Use Cases for Sleep Function in TypeScript

Let’s look at some practical scenarios where I’ve found sleep functions particularly useful:

1. Rate Limiting API Calls

When working with APIs that have rate limits, adding delays between requests is essential:

async function fetchUserById(id: number) {
  console.log(`Calling API for user ID: ${id}`);
  await sleep(100); // Simulate API response time
  return { id, name: `User ${id}` };
}

// Sleep utility
function sleep(ms: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// Final version of fetchAllUsers with logs
async function fetchAllUsers(userIds: number[]) {
  const results = [];

  console.log('Starting to fetch user data...');

  for (const id of userIds) {
    console.log(`Fetching user with ID: ${id}`);

    const userData = await fetchUserById(id);
    console.log(`Fetched data for user ${id}:`, userData);

    results.push(userData);

    console.log(`Waiting 300ms before next request...`);
    await sleep(300);
  }

  console.log('Finished fetching all users.');
  return results;
}

// Example usage
fetchAllUsers([101, 102, 103]).then(users => {
  console.log('Final user list:', users);
});

Output:

Limiting API Calls using Sleep Functions in TypeScript

2. Creating Animations or Transitions

For UI animations that require precise timing:

async function animateProgressBar(elementId: string, targetPercent: number) {
  const element = document.getElementById(elementId) as HTMLElement;
  let current = 0;

  while (current < targetPercent) {
    current += 1;
    element.style.width = `${current}%`;
    element.textContent = `${current}%`;

    // Smooth animation with small delays
    await sleep(20);
  }
}

3. Testing Race Conditions

When testing asynchronous code for potential race conditions:

async function testConcurrentOperations() {
  // Start two operations with different delays
  const operation1 = async () => {
    await sleep(100);
    return "Operation 1 result";
  };

  const operation2 = async () => {
    await sleep(50);
    return "Operation 2 result";
  };

  // Execute concurrently
  const results = await Promise.all([operation1(), operation2()]);
  console.log("Results:", results);
}

Output:

Test race conditions using Sleep function in TypeScript

Check out: Create an Object from an Interface in TypeScript

Potential Pitfalls and Best Practices

While implementing sleep functions in TypeScript, I’ve encountered some common issues. Here are my recommendations:

  1. Don’t use sleep in critical rendering paths: Sleep functions pause execution, which can block UI updates if used improperly.
  2. Be mindful of memory usage: Avoid creating many pending promises in loops without proper throttling.
  3. Consider using cancelable sleep: For scenarios where you might need to cancel a sleep operation:
function cancelableSleep(ms: number) {
  let timeoutId: NodeJS.Timeout;

  const promise = new Promise<void>((resolve) => {
    timeoutId = setTimeout(resolve, ms);
  });

  const cancel = () => {
    clearTimeout(timeoutId);
  };

  return { promise, cancel };
}

// Usage
const { promise, cancel } = cancelableSleep(5000);

// Later, if needed
cancel(); // Cancels the sleep operation

Output:

Cancel sleep operation in TypeScript
  1. Use TypeScript’s typing for cleaner code: Properly typed sleep functions make your code more maintainable.

I hope you found these methods for implementing sleep functions in TypeScript helpful. These approaches have served me well across numerous projects, from small utilities to large enterprise applications.

Remember that while sleep functions are useful, they should be used judiciously. For most UI work, consider using CSS animations or requestAnimationFrame for smoother performance. For backend operations, evaluate whether actual timers or event-based approaches might be more appropriate than explicit sleep calls.

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.