Engineer bro!

Mon Feb 21 2022 (3 months ago)

Engineer by mistake!

I am a software engineer by passion

JavaScript Interview Question | Create setInterval() using setTimeout()

This is a very hot question in the JavaScript world. It has been asked so many times in the JavaScript interview. In this article, I'll try to explain to you the concept behind this.

Table of contents

Prerequisite

This question requires that you should have basic understanding of JavaScript, execution context, closures, setTimeout, setInterval and recursion. Although, I'll try to cover a few of them in the article itself.

What is setTimeout()?

setTimeout() is an API provided by a JavaScript execution environment. It is used to execute a specific set of code after some time.

setTimeout(()=>{
    console.log("Log me after 2 seconds :)")
},2000)

The above function will print Log me after 2 seconds :) after 2 seconds. It might not print it after exactly 2 seconds, because your thread can be busy at that time.

Learn more about it here

What is setInterval()?

setInterval() is an API provided by JavaScript execution environment, which is used to execute the specific set of code at some time interval.

setInterval(()=>{
    console.log("Log me after every 1 seconds...");
},1000);

Learn more about it here

What is recursion?

In computer science, recursion is a method of solving a computational problem where the solution depends on solutions to smaller instances of the same problem.

In simple terms, when a function call itself, then it is called recursion.

function recur(){
    console.log("Recursion ... ");
    recur();
}

recur();
/*
O/P 
Recursion ... 
Recursion ... 
Recursion ... 
...
*/

Let's create setInterval()

Before creating setInterval, let's note down the parameters and return value.

Parameters passed in setInterval()

  • func - a function is passed, that will be executed at a specific time interval.

  • delay - the amount of interval in milliseconds, default is 0.

  • args - arguments that will be passed to the callback function.

Return value of setInterval()

  • intervalID - It is a numeric, non-zero value which identifies the timer created by the call to setInterval(). This value can be passed to clearInterval() to cancel the interval.

Let's define customInterval()

// cb - callback function
// delay - the amount of interval
function customInterval(cb,delay){
    // logic goes here...
}

Now, i have defined the customInterval(), so first we would have to execute the provided callback function at the given time interval.

// cb - callback function
// delay - the amount of interval
function customInterval(cb, delay) {
  setTimeout(() => {
    cb();
    
    // use recursion to call the call back again
    customInterval(cb, delay);
  }, delay);
}

customInterval(
  () => console.log("Interval-", new Date().toLocaleTimeString()),
  1000
);

// output
Interval- 12:26:14 pm
Interval- 12:26:15 pm
Interval- 12:26:16 pm
...

Now, the function is being called at the given time interval, but how can we clear the interval. To clear the customInterval we need the timer id returned by setTimeout.

But, the hack is here is that we need the latest timer id returned by setTImeout.

Let's clear the interval

As i have mentioned that, we need the id returned by setTimeout for clearing the interval. But, we are calling the above function in recursion. A function can return a value only one time, so how do we get the id of the latest setTImeout out of the function customInterval.

Let's have a look at the below function.

function test() {
  let value = 0;
  value++;
  console.log("Value inside test - ", value);
  setTimeout(test, 1000);
  return value;
}

let value = test();

setInterval(() => {
  console.log("Value outside test - ", value);
}, 1000);

The above code is just for testing

When you execute the above code, you will get the below output.

Value inside test -  1
Value inside test -  1
Value outside test -  1
Value inside test -  1
Value outside test -  1
....

There is two questions is arising from the above output

  • Why value inside the function is not updating- because we are setting value=0value = 0 in each function call.

  • Why value outside the function is not updating - because a function can return a value only once.

So, the question is that how can we get updated value outside the function?
The answer is by creating a closure.

Have a look at the below code.

function test() {
  let item = {
    value: 0,
  };
  
   // this function will create a closure
  function inc() {
    item.value++;
    console.log("Value inside test ", item.value);
    setTimeout(inc, 1000);
  }
  inc();
  return item;
}

let item = test();

setInterval(() => {
  console.log("Value outside test - ", item.value);
}, 1000);

When you execute the above code, you will get the below output.

Value inside test  1
Value inside test  2
Value outside test -  2
Value inside test  3
Value outside test -  3
Value inside test  4
Value outside test -  4
Value inside test  5

As you can see in the above function, we are getting the updated value outside the function, this is just because of closure created by inc() function.

Here the closure is created by inc() function which will remain till inc() will executed. And we are calling the inc() function recursively, so it'll be there always.

Final Touch

As you have seen in the previous section, we are able to get the updated value outside the function at some time interval. So, we can use the above concept to get the id of the latest setTimeout outside the customInterval to clear the timer. Once the timer is cleared using clearTimeout, it'll automatically stop.

function customInterval(fn, delay) {
  const interval = {
    id: null,
  };

  function timeOut() {
    interval.id = setTimeout(() => {
      fn();
      timeOut();
    }, delay);
  }
  timeOut();
  return interval;
}

const timer = customInterval(() => {
  console.log("In Side Custom Interval");
}, 1000);

setTimeout(() => {
  console.log("Called clear interval");
  clearTimeout(timer.id);
}, 5000);

When you execute the above function, you'll get the below O/P.

In Side Custom Interval
In Side Custom Interval
In Side Custom Interval
In Side Custom Interval
Called clear interval

As you can see in the above function, an object interval is returned by the customInterval. We are storing the reference of interval inside timer variable outside the function.

So, whenever timeOut will update interval.id, we can get it's updated value in timer.id function.

As you can see we have used clearTimeout(timer.id);. This basically clears the timer.

Thank You ❤️

JavaScriptNodeJsSoftware Engineering

Comments (0)

Discussions (0)


© 2021 dsabyte. All rights reserved