Frontend Development 12 min read

Understanding JavaScript setTimeout and setInterval and Implementing setInterval Using setTimeout

This article explains the fundamentals and execution order of JavaScript's setTimeout and setInterval functions, discusses their parameters and return values, demonstrates why setTimeout is asynchronous, shows how to cancel timers, and provides a custom recursive setTimeout solution that mimics setInterval behavior.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Understanding JavaScript setTimeout and setInterval and Implementing setInterval Using setTimeout

Preface

In a previous interview I was asked to implement setInterval using setTimeout , which I failed to answer. This article revisits that challenge and explains timers in depth.

Overview

The article covers the basics of setTimeout and setInterval , their execution order, and finally presents an interview question: using setTimeout to implement setInterval . Readers can skip to the final solution if they wish.

Timers

JavaScript is a single‑threaded language; all tasks run on the main thread. Asynchronous operations such as timers and network requests are handled by the event loop, which queues callbacks until the main thread is idle.

setTimeout and setInterval Functions

Both functions are similar, so they are taught together for better understanding.

Function Comparison

setTimeout : Executes a callback once after a specified delay (in milliseconds).

setInterval : Repeatedly executes a callback at fixed intervals, similar to repeatedly calling setTimeout .

Parameter Structure

Both accept similar arguments:

callback : Function to run when the timer expires.

time : For setTimeout this is the delay; for setInterval it is the interval between executions. Non‑numeric values are treated as 0 , as are negative numbers.

[arg1, arg2, ...] : Optional arguments passed to the callback.

Return Value

Both setTimeout and setInterval return a non‑zero integer timer ID, which can be used to cancel the timer.

Why is setTimeout Asynchronous?

Consider the following code:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Timer</title>
</head>
<body>
<script>
setTimeout(function(){
console.log('hello world');
},10000)
console.log(123)
</script>
</body>
</html>

The output will be:

123 hello world

Explanation: setTimeout places its callback into the event loop; the callback runs only after the main thread finishes executing the current script, which is why 123 logs first.

Does setTimeout Always Execute After the Specified Time?

No. If the main thread is blocked (e.g., an infinite loop) or the page is closed before the timer fires, the callback will not run.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Timer</title>
</head>
<body>
<button id="btn2">Stop</button>
<script>
setTimeout(function(){
console.log('hello world');
},1000);
while(true){}
</script>
</body>
</html>

How to Cancel a Timer

Use the timer ID returned by setTimeout or setInterval with clearTimeout or clearInterval .

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn">Stop Timer</button>
<script>
const interval = setInterval(function(){
console.log('hello world');
},1000);
console.log(interval);
const btn = document.getElementById('btn');
btn.onclick = function(){
clearInterval(interval);
};
</script>
</body>
</html>

Clicking the button stops the repeated logging.

Example: Implementing setInterval with setTimeout

Problem Statement

Use setTimeout recursively to mimic the behavior of setInterval .

Solution Code

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function customSetTimeout(fn,time){
let intervalID=null;
function loop(){
intervalID = setTimeout(()=>{
fn();
loop();
},time);
}
loop();
return ()=>clearTimeout(intervalID);
}
const interval = customSetTimeout(function(){
console.log('hello world');
},1000);
setTimeout(()=>{
interval();
},5000);
</script>
</body>
</html>

Process Analysis

Define customSetTimeout : Accepts a callback fn and a delay time .

Store timer ID : Variable intervalID holds the current setTimeout ID.

Recursive loop function : Calls setTimeout , runs fn after time , then calls itself to continue the cycle.

Start first loop : Invoking loop() begins the first timeout.

Return a cancel function : The returned arrow function clears the active timeout, allowing the loop to be stopped.

Use the custom timer : Create interval by calling customSetTimeout , which logs “hello world” every second.

Stop after 5 seconds : A separate setTimeout calls the cancel function, ending the repeated logging.

Conclusion

By using a recursive setTimeout we can replicate setInterval functionality and also gain precise control over when to stop the timer.

frontendJavaScriptTimersetTimeoutsetInterval
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.