Asynchronous Javascript: Handling Delays

Before committing to web development as a career, I had already dabbled with a few programming languages like Python, C++, and Matlab. This gave me a big head start in becoming proficient in Javascript, but did not prepare me for asynchronous programming. Asynchronous programming was definitely the biggest challenge to me as a beginner, and I distinctly remember feeling hopelessly confused when trying to use AJAX for the first time. At the time, my code looked something like this:

1

Soon I realized that there is no guarantee that your lines of code will execute in the order that you have written them. While this behaviour can be confusing for newcomers to understand (and is often a cause of headaches for even experienced devs), it is actually desirable because it allows our program to handle other tasks while it waits for something else (eg a timer to expire or a response from a server). This post is the first of a series that focuses on explaining this behaviour and sharing a few ways to handle it.

It is sometimes desirable for a program to wait some length of time before executing. For example in Simon it is important for the game to show the pattern one color at a time. How can this be done?

Many programming languages have a function called sleep that will pause the execution of the code following it for a specified length of time. Javascript has no such function, and it would not be a good solution even if it did exist because it would block all the other code in our program.

Instead we have the setTimeout method which accepts a function (typically called a callback) and a length of time in milliseconds. Here’s a basic example:

1

Notice that the final line, foo = 'baz', runs before the timeout has completed.

Similar to the setTimeout method, the setInterval method is available to repeat a function on a specified interval indefinitely.

1

Both methods return a timeoutID that can be passed to another method called clearInterval to cancel any pending callbacks. This can be used to repeat a function for a set number of cycles.

1

What if it becomes necessary to execute a series of different callbacks with different delays? One solution could look like this

1

This can be used if we know the number of preset callbacks that we want to execute (3 in this case), but what if we had a lot of callbacks that we wanted to fire one at a time with differing delays, or what if the number of callbacks is not always the same? Hardcoding nested callbacks is not a good solution in this case.

Recursion is one technique that can be used to achieve the above requirements.

1

Here, the doTasksOneAtATime function will check that the array passed to it has at least one entry, execute the first task in the array, remove this task, and then call itself again with the shortened tasks array provided as an argument. Notice that this enables different delays and callbacks to be used (setting a delay to 0 will causes callbacks to execute at the same time), and supports tasks arrays of any length. This provides a lot of flexibility for usage, and also improves the readability by allowing tasks to be organized into arrays.

Summary

Handling delayed sequences in Javascript can seem hard at first, but the added complexity allows us to avoid code that is blocking. Furthermore, the setTimeout and setInterval methods can be structured to handle almost any situation.