Let’s say you want to log three messages to JavaScript’s console, with a delay of one second between each one. There’s no sleep() method in JavaScript, so you try to use the next best thing, setTimeout(), which sets a timer to execute the specified code.

Unfortunately, setTimeout() doesn’t work as you might expect. You may have tried it at some point in a JavaScript loop and seen that setTimeout() doesn’t work at all.

How to Write a Sleep Function in JavaScript

The simplest way to create a sleep function in JavaScript is to use the Promise, await and async functions in conjunction with setTimeout(). Await causes the code to wait until the promise object is fulfilled, operating like a sleep function. You can also pass staggered, increasing setTimeout() functions to simulate a sleep function. 

The problem arises from misunderstanding setTimeout()as a sleep() function, when it actually works according to its own set of rules.

In this article, I explain how to use setTimeout(), including how you can use it to make a sleep function that will cause JavaScript to pause execution and wait between successive lines of code.

 

How to Use SetTimeout in JavaScript

If you just quickly skim the setTimeout() documentation, it seems to take a “delay” parameter measured in milliseconds.

Going back to the original problem, if you try to call setTimeout(1000) to wait for one second between your calls to the console.log() function, it won’t work.

setTimeout(1000)
console.log("First")
setTimeout(1000)
console.log("Second")
setTimeout(1000)
console.log("Third")

for (let i = 1; i <= 3; i++) {
  setTimeout(1000)
  console.log(`#${i}`)
}

The result is no delay at all. It’s as if setTimeout() didn’t exist.

Looking back at the docs, you’ll note that the first argument is actually supposed to be a function call, not the delay. After all, setTimeout() isn’t actually a sleep() method.

However, if you rewrite your code to have a callback function as the first argument and the requisite delay as the second parameter, it still won’t produce the desired result:

setTimeout(() => console.log("First"), 1000)
setTimeout(() => console.log("Second"), 1000)
setTimeout(() => console.log("Third"), 1000)

for (let i = 1; i <= 3; i++) {
  setTimeout(() => console.log(`#${i}`), 1000)
}

This results in all three console log messages being displayed together, after a single delay of 1,000 ms (one second), instead of the desired effect of a delay of one second between each repeated call.

Before we talk about how to fix the issue, let’s examine the setTimeout() function in a little bit more detail.

More on JavaScriptCurrying in JavaScript Explained With Examples

 

Examining setTimeout()

You may have noticed the use of arrow functions in the second code snippet above. Those are necessary because you need to pass an anonymous callback function to setTimeout() that will run the code you want executed after the timeout.

In the anonymous function, you can specify any arbitrary code to be executed after the timeout period:

// Using an anonymous callback function with the arrow syntax:
setTimeout(() => console.log("Howdy!"), 1000)

// This is equivalent to using the function keyword:
setTimeout(function () { console.log("Howdy!") }, 1000)

Theoretically, you can just pass the function as the first argument, and the arguments to that callback function as the remaining parameters. But that never seems to work right for me:

// Should work but doesn't
setTimeout(console.log, 1000, "Howdy!")

People work around this using a string, but that isn’t recommended. Executing JavaScript from a string is a security risk, as any bad actor could run arbitrary code injected as a string.

 // Shouldn't work but does:
setTimeout(`console.log("Howdy!")`, 1000)

So, why did setTimeout() fail in our first set of code examples? It seemed like we were using it correctly, with a repeated delay of 1000ms each time.

That’s because setTimeout() is executed as synchronous code, and the multiple calls to setTimeout() all run at the same time. Each call to setTimeout() creates asynchronous code that will execute later, after the given delay. Since each delay in the code snippet was the same (1000ms), all the queued code ran at the same time, after a single delay of one second.

As noted, setTimeout() is not actually a sleep() function; instead, it just queues asynchronous code for later execution. Fortunately, it’s possible to use setTimeout() to create your own sleep() function in JavaScript.

 

How to Write a Sleep Function in JavaScript

Through the power of Promise, async (async) and await (await), you can write a sleep() function that will work as you would expect it should.

However, you can only call this custom sleep() function from within async functions, and you need to use the await keyword with it.

This code snippet demonstrates how to write a sleep() function:

const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay))

const repeatedGreetings = async () => {
  await sleep(1000)
  console.log("First")
  await sleep(1000)
  console.log("Second")
  await sleep(1000)
  console.log("Third")
}

repeatedGreetings()

This JavaScript sleep() function works exactly as you might expect, because await causes the synchronous execution of the code to pause until the Promise is resolved.

A tutorial on how to create JavaScript sleep function with async and await. | Video: Coding With Adam

More on JavaScriptJavaScript Call Stacks: An Introduction

 

JavaScript Sleep Function Alternatives

Alternatively, you can specify increasing timeouts when you call setTimeout() in the first place. The following code is equivalent to the last example:

setTimeout(() => console.log("First"), 1000)
setTimeout(() => console.log("Second"), 2000)
setTimeout(() => console.log("Third"), 3000)

Using increasing timeouts works because the code is all executed at the same time, so the specified callback functions will be executed one, two and three seconds from the time of the execution of the synchronous code.

I like this method a lot, although you can’t create a sleep function that works this way without tracking (or guessing) what the timeout should be using a variable.

 

Can JavaScript Sleep Function Work In Loops?

Either of the above options to pause JavaScript execution will work fine in loops, as you might expect. Let’s look at two quick examples.

Here’s a code snippet using a custom sleep() function:

const sleepNow = (delay) => new Promise((resolve) => setTimeout(resolve, delay))

async function repeatedGreetingsLoop() {
  for (let i = 1; i <= 5; i++) {
    await sleepNow(1000)
    console.log(`Hello #${i}`)
  }
}

repeatedGreetingsLoop()

And here is a code snippet with the simpler use of increasing timeouts:

for (let i = 1; i <= 5; i++) {
  setTimeout(() => console.log(`Hello #${i}`), 1000 * i)
}

Again, I prefer the latter syntax, particularly in loops.

More on JavaScriptHow to Use JSON.stringify() and JSON.parse() in JavaScript

 

Best Ways to Create a JavaScript Sleep Function

JavaScript doesn’t have a sleep() or wait() function, but it’s easy to create one using the built-in setTimeout() function, as long as you are careful with how you use it.

By itself, setTimeout() does not work as a sleep() function, but you can create a custom JavaScript sleep() function using async and await.

Taking a different approach, you can pass staggered (increasing) timeouts to setTimeout() to simulate a sleep() function. This works because all the calls to setTimeout() execute synchronously, just like JavaScript usually does.

Hopefully this helps you introduce some delay into your code using vanilla JavaScript, without any need for external libraries or frameworks.

Expert Contributors

Built In’s expert contributor network publishes thoughtful, solutions-oriented stories written by innovative tech professionals. It is the tech industry’s definitive destination for sharing compelling, first-person accounts of problem-solving on the road to innovation.

Learn More

Great Companies Need Great People. That's Where We Come In.

Recruit With Us