How to set multiple setTimeouts start at the same time but with different time delays on Node.js?

Viewed 23

I was just a little curious about using setTimeout inside an async function so I tried to do something like this:

const { setTimeout } = require('timers/promises');

async function secondsToWait(sec) {
    await setTimeout(sec * 1000);
}

async function printSomething() {
    console.log(1);
    await secondsToWait(1);
    console.log(2);
    await secondsToWait(2);
    console.log(3);
    await secondsToWait(3);
    console.log(4);
}

Now, what I'm expecting is to print 1 immediately, then print 2 after a second, then print 3 after a second, then print 4 after a second...

The thing is after it prints 2 after a second has passed, it prints 3 after 2 seconds has passed, and prints 4 after 3 seconds has passed.

I was expecting it to behave like the typical setTimeout function outside Node.js where after the functions secondsToWait(1), secondsToWait(2), secondsToWait(3) are invoked their timers start at the same time but finishes differently based on their time delays.

setTimeout(() => { print something }, 1000);
setTimeout(() => { print something }, 2000);
setTimeout(() => { print something }, 3000);

So how can I do something like this in Node.js without using the traditional setTimeout function of JavaScript? Preferrably using it within an async function?

I've tried to modify the asynchronous secondsToWait() function to this:

await function secondsToWait(sec) {
    sec = 1;
    await setTimeout(sec * 1000);
}

I've just permanently set the time delay seconds to 1, so no matter what the time that will be passed into the function it will always have a 1 second time delay. Well obviously, I just fooled myself doing this...

So how can I do this using the setTimeout from 'timers/promises' module? Is this even possible?

1 Answers

The code doesn't do what you expect because your expectation is wrong.

await will literally wait. So it prints 1, then waits 1 seconds, prints 2, then waits 2 seconds, etc.

What you're describing is something like:

setTimeout(() => console.log(1), 1000);
setTimeout(() => console.log(2), 2000);
setTimeout(() => console.log(3), 3000);
setTimeout(() => console.log(4), 4000);

Where all the timeouts get queued all at once.

If you want it to wait 1 second in between prints then do:

async function printSomething() {
    console.log(1);
    await secondsToWait(1);
    console.log(2);
    await secondsToWait(1); // always 1
    console.log(3);
    await secondsToWait(1); // again, just 1
    console.log(4);
}
Related