Creating Timed Sequences in Javascript

When you start working in Javascript and building apps and webpages, you get used to running code based on inputs - someone pressed a button, and then your code gets to run.

This is fine for most webpages, but what if you want to to make changes on the page without user input, but slow enough for the user to take in.

Today I'm going to show you how to use Javascript's inbuilt setTimeout function to execute code on a timer.

Creating the timing

setTimeout is an inbuilt function that runs a provided function after a set period of time (set in milliseconds, so 1000 = 1 second). These timings aren't massively precise (it might run 2ms late), but precise enough for anything the user will be able to notice.

When we want to create a sequence of these timed events, we need to create a loop using the setTimeout function. A naïve approach is to use a good ol' for loop:

for (let i = 0; i < 3; i++) {
    // Bad example, this doesn't work
	setTimeout(function() { console.log("hello"); }, 500);
}

Sadly, this doesn't work - what happens instead is that we queue up 3 functions, all of them triggering at once in 500ms. Not quite the sequence we were after.

What we actually need to do is have code run at 500ms, 1000ms, 1500ms and so on. There are two ways this can be done: Use setInterval, which is effectively setTimeout but does it every 500ms, or we can call setTimeout at the end of each setTimeout call to set up a loop.

There are reasons to do both, so here's a guideline:

  1. If you want to call the same function on the same interval, then you should use setInterval. Keep in mind this keeps going on forever until you tell it to stop.
  2. If you want to call different functions, or on different intervals, then you should use setTimeout.

Although setInterval would be more appropriate for our specific example, I'm going to use setTimeout.

function sayHello() {
	console.log('hello');
	setTimeout(sayHello, 500);
}

setTimeout(sayHello, 500);

Now we have function that runs every 500ms!.. except that the loop never stops. I want this function to only run 3 times, so I'll need a way to make sure that we stop running when the loop is done.

let index = 0;

function sayHello() {
	console.log('hello');
	index += 1;

	// We increment index before we get here because this code is to see if we
	// need to do the *next* loop in the sequence. This if condition acts like
	// the condition in a while loop
	if (index < 3) {
		setTimeout(sayHello, 500);
	}
}
                  
setTimeout(sayHello, 500);

Making a sequence

I didn't promise you instructions on how to make a timer though – I promised you instructions on how to make a sequence - after all a function that spits out the same message every 500ms is a bit boring.

What we need to do is make it so that function we call does something different every time – If you can get away with using variables to change one function, you should do that, but if you need to do something more complex, you can just call different functions with each setTimeout call.

let messages = [
	'Hello, welcome to my tutorial',
	'It seems you\'re new here',
	'Don\'t forget to sign up to my mailing list',
];
let index = 0;

function sayMessage() {
	console.log(messages[index]);
	index += 1;

	if (index < messages.length) {
		setTimeout(sayMessage, 500);
    }
}
                                
setTimeout(sayMessage, 500);

A visual example

Can't get past JavaScript Tutorials?

Download my FREE ebook on how to succeed as a self-taught JavaScript Developer, and how to find projects that you'll actually finish. Learn More...