JavaScript doesn't have a built-in sleep() function like other languages. When you need to pause execution — to simulate loading, delay API calls, or wait for animations — you have to work with JavaScript's asynchronous nature.
I've built enough timers, loading states, and delayed actions to know the patterns that actually work. Here's how to wait 5 seconds in JavaScript without blocking the UI.
// Simple delay using setTimeout
setTimeout(() => {
console.log("5 seconds have passed");
}, 5000);
That's the basic approach. But there are cleaner patterns, especially when you need sequential code execution.
How Does setTimeout() Work?
setTimeout() schedules a function to run after a delay in milliseconds:
console.log("Start");
setTimeout(() => {
console.log("This runs after 5 seconds");
}, 5000);
console.log("End");
Output:
Start
End
This runs after 5 seconds
Notice "End" prints before the delayed message. setTimeout() is non-blocking — JavaScript continues executing the next lines while waiting. This is fundamental to how JavaScript handles asynchronous operations.
I use setTimeout() for simple delays: hiding notification toasts, debouncing user input, or adding artificial delays in demos.
How Do I Wait Before Running the Next Line?
You can't block execution in JavaScript (and you shouldn't — it would freeze the browser). Instead, use async/await with Promises:
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function demo() {
console.log("Start");
await sleep(5000);
console.log("This runs after 5 seconds");
console.log("End");
}
demo();
Output:
Start
This runs after 5 seconds
End
Now the code executes sequentially. The await keyword pauses the async function until the Promise resolves.
I use this pattern constantly: waiting for API responses, coordinating animations, or building sequential tutorials that step through content.
Can I Use Promises Without async/await?
Yes, with .then():
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
console.log("Start");
sleep(5000).then(() => {
console.log("This runs after 5 seconds");
console.log("End");
});
This works, but nesting .then() calls gets messy quickly. I prefer async/await for readability.
What About setInterval()?
setInterval() runs a function repeatedly at intervals. You can use it for a one-time delay by clearing it immediately:
console.log("Start");
let timer = setInterval(() => {
console.log("5 seconds passed");
clearInterval(timer);
}, 5000);
console.log("End");
This is overkill for simple delays. Use setTimeout() instead. I only use setInterval() for repeated actions — countdown timers, polling servers, or animation loops.
How Do I Cancel a Timeout?
setTimeout() returns a timer ID. Pass it to clearTimeout() to cancel:
let timerId = setTimeout(() => {
console.log("This won't run");
}, 5000);
clearTimeout(timerId); // Cancel the timeout
I use this for search input debouncing. When a user types, I set a timeout to trigger the search after 500ms. If they type again, I cancel the previous timeout and start a new one. This prevents flooding the server with requests on every keystroke.
Can I Wait Multiple Times in Sequence?
Stack await calls:
async function sequentialDelays() {
console.log("Start");
await sleep(2000);
console.log("2 seconds");
await sleep(3000);
console.log("5 seconds total");
await sleep(5000);
console.log("10 seconds total");
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
sequentialDelays();
Each await pauses execution until the delay completes. I built a tutorial walkthrough that used this pattern to highlight UI elements in sequence.
How Does This Apply to PDF Generation?
When generating PDFs from dynamic content, sometimes you need to wait for JavaScript to execute before rendering. Here's how I use delays with IronPDF for Node.js:
import { PdfDocument } from "@ironsoftware/ironpdf";
async function generatePdfWithDelay() {
const html = `
<html>
<body>
<h1>Report Generated</h1>
<div id="chart">Loading chart...</div>
<script>
setTimeout(() => {
document.getElementById('chart').innerHTML =
'<img src="chart.png" alt="Sales Chart" />';
}, 2000);
</script>
</body>
</html>
`;
// Wait for JavaScript to execute
await sleep(5000);
const pdf = await PdfDocument.fromHtml(html);
await pdf.saveAs("Report.pdf");
console.log("PDF created after content loaded");
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
generatePdfWithDelay();
IronPDF uses a Chromium rendering engine, so JavaScript in your HTML executes before PDF generation. The delay ensures dynamic content finishes loading.
I've used this for dashboards where charts render client-side with Chart.js or D3. Without the delay, the PDF captures the "Loading..." state instead of the actual chart.
The complete guide to JavaScript delays covers more advanced scenarios like recursive timeouts and Promise.race for maximum wait times.
What's the Difference Between Delay and Debounce?
Delay: Wait a fixed time, then execute once.
setTimeout(() => {
console.log("Delayed action");
}, 5000);
Debounce: Wait until user stops taking action, then execute.
let debounceTimer;
function debounce(fn, delay) {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(fn, delay);
}
// Usage: call this on every keystroke
debounce(() => {
console.log("User stopped typing");
}, 500);
Debouncing is critical for search inputs, window resize handlers, and scroll events. Without it, you'd fire hundreds of expensive operations per second.
Can I Use Delays in Loops?
Yes, but regular loops won't work as expected:
// This WON'T work as expected
for (let i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i); // Prints 5 five times
}, 1000);
}
All timeouts are scheduled immediately, then fire 1 second later. By that time, the loop finished and i is 5.
Use async/await:
async function delayedLoop() {
for (let i = 0; i < 5; i++) {
console.log(i);
await sleep(1000);
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
delayedLoop(); // Prints 0, 1, 2, 3, 4 with 1-second gaps
I used this pattern for a tutorial that stepped through code examples one at a time.
How Accurate Are JavaScript Timers?
Not very. setTimeout(fn, 5000) means "execute after at least 5 seconds." Browser tabs in the background throttle timers to save CPU. Heavy JavaScript execution can delay timer callbacks.
For precise timing, use performance.now():
const start = performance.now();
setTimeout(() => {
const elapsed = performance.now() - start;
console.log(`Actual delay: ${elapsed}ms`); // Often 5001-5020ms
}, 5000);
If you need frame-perfect timing for animations, use requestAnimationFrame() instead.
Quick Reference
| Task | Method |
|---|---|
| Simple delay | setTimeout(fn, ms) |
| Sequential code |
async/await with Promise |
| Cancel timeout | clearTimeout(timerId) |
| Repeated action | setInterval(fn, ms) |
| Debounce input |
clearTimeout + setTimeout
|
| Loop with delays |
async/await in loop |
| Precise timing | performance.now() |
The key is understanding that JavaScript is single-threaded and asynchronous. You're not blocking execution; you're scheduling callbacks. Once you internalize that, timers make sense.
Written by Jacob Mellor, CTO at Iron Software. Jacob created IronPDF and leads a team of 50+ engineers building .NET document processing libraries.
Top comments (0)