- 4 minutes read

Your computer is never fast enough. However, in rare cases, you need to slow down. In my case, is was OpenStreetMap that forced me to go a slower pace. The free plan only allows one access per second, so I had to make my node.js program pause a second between two accesses.

As it turns out, you can't do that in node.js. Luckily, modern node.js allows you to simulate the feature so you hardly notice the difference.

What about using a library?

In the JavaScript worlds, there's a library for everything. Even for sleeping. But you shouldn't use it.

I'm talking about the library called sleep (i.e. the one you install with npm install sleep). At first glance, it's exactly the library you're looking for. It offers methods to stop the execution of your node.js application for a couple of seconds, milliseconds, or microseconds.

At second glance, you'll see the large print on the npm site. The library follows a "stop the world" approach. That may be great for debugging, but it stops everything. If you've initiated a REST call, it won't be processed until the sleep period is over.

In my case, that's not what I needed. I wanted to delay the main thread for a second, but I didn't want to stop the secondary thread to process the result of the REST call. Only there's no such thing as a secondary thread in node.js. There's only one thread with an event loop. The sleep library pauses precisely this event loop.

Pausing the "main" thread without stopping the "secondary" threads

It's important to keep in mind there's only one thread in node.js. Multi-threading may be a useful metaphor, but in reality the only way to simulate it is to use setTimeout() or setInterval().

So that's the general approach. You wrap the code you want to execute later in a function, which is executed by a setTimeout() call. The idea is sketched in this StackOverflow answer:

function function1() { // stuff you want to happen right away console.log('Welcome to My Console,'); } function function2() { // all the stuff you want to happen after that pause console.log('Blah blah blah blah extra-blah'); } // call the first chunk of code right away function1(); // call the rest of the code and have it execute after 3 seconds setTimeout(function2, 3000);

A simpler approach

From a technical point of view, that's the end of the story. It's precisely what I ended with. But from a semantical point of view, there's a lot to be improved. Remember, what I wanted to program was something like this:

var largeBunchOfGPSCoordinates = [{...}, {...}, ..., {...}]; for (var coordinate of largeBunchOfGPSCoordinates) { console.log(determineCity(coordinate)); sleep(1000); }

You can express this with setTimeout(), but it's going to be clumsy.

Async/Await to the rescue

Modern JavaScript helps you with async and await. You can express the algorithm like so:

var largeBunchOfGPSCoordinates = [{...}, {...}, ..., {...}]; function sleep(millis) { return new Promise(resolve => setTimeout(resolve, millis)); } async function examineCoordinates() { for (var coordinate of largeBunchOfGPSCoordinates) { console.log(determineCity(coordinate)); await sleep(1000); } } examineCoordinates();

JavaScript internally unwraps the for loop in a sequence of promises. The next loop is started by the resolve callback of the sleep method.

From a programmers perspective, that's a nice an clean solution. You only have to add the keywords async and await. Apart from that, the programming model doesn't change much.

forEach()

For some reason, this approach only works with the traditional for loop. It does not work with the fancy, functional forEach() method.

Wrapping it up

Node.js doesn't allow you to put the application asleep, but you can simulate this by using setTimeout(). That, in turn, throws you directly into callback hell. There's nothing you can do about this. But async / await offers nice syntactic sugar to make the callback hell go away, if only virtually.


Comments