Simplify code by promisifying `setTimeout`
PuruVJ

PuruVJ @puruvj

Location:
Jaipur, Rajasthan, India
Joined:
Sep 30, 2019

Simplify code by promisifying `setTimeout`

Publish Date: Sep 28 '20
5 7

Originally Published @ puruvj.dev

Recently, when I was working on my practice project Microsoft Todo Clone, I needed to implement code like this:

#1 Do Task 1
#2 Wait for 200ms
#3 Do task 2
#4 Wait for 200ms
#5 Do Task 3
Enter fullscreen mode Exit fullscreen mode

Notice #2 and #4. They smell of setTimeout😖. setTimeout takes in a callback, meaning there will be an indentation. Whenever those appear, means the code's gonna get ugly.

So I wrote this code in JS

doTask1();

setTimeout(() => {
  doTask2();

  setTimeout(() => {
    doTask3();
  }, 200);
}, 200);
Enter fullscreen mode Exit fullscreen mode

Now you can see for yourself, this code SMELLS. BAD.

The moment I wrote it, I knew it wouldn't work in long-term. What if I needed to an extra step of waiting and doing a Task #4? Or rearranging the order.

So, I declared a utility function and it solved the problem completely.

/**
 * @param {number} time Time to wait for in milliseconds
 */
function waitFor(time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}
Enter fullscreen mode Exit fullscreen mode

Here we're returning a Promise, which resolves when the setTimeout function inside runs.

It's usage would be as simple as

await waitFor(200);
Enter fullscreen mode Exit fullscreen mode

So the spaghetti code above could be rearranged like this:

doTask1();

await waitFor(200);

doTask2();

await waitFor(200);

doTask3();
Enter fullscreen mode Exit fullscreen mode

See how simple it became? It reads exactly like the text version I wrote at the top. It's very idiomatic 😎.

Shorter code

That code snippet could be simplified further

const waitFor = (time) => new Promise((resolve) => setTimeout(resolve, time));
Enter fullscreen mode Exit fullscreen mode

Comments 7 total

  • 𒎏Wii 🏳️‍⚧️
    𒎏Wii 🏳️‍⚧️Sep 28, 2020

    I'd use the chance to change the time argument to use seconds because who the fuck thought milliseconds were acceptable?

    • Mark Witt
      Mark WittSep 28, 2020

      Change setTimeout(resolve, time) to setTimeout(resolve, time * 1000)

      • 𒎏Wii 🏳️‍⚧️
        𒎏Wii 🏳️‍⚧️Sep 28, 2020

        Yes, thanks but I was already well aware of how to convert milliseconds to seconds ;D

    • PuruVJ
      PuruVJSep 28, 2020

      You can sure change it. What Mark suggested would work.

      However, I disagree with your point. I've used more timers less than 1 second or timeouts like 1.5 seconds that I kinda find the milliseconds method better. Plus its so standard thanks to langs like Java and C and our own JS that any API respecting seconds would feel plain weird

      • 𒎏Wii 🏳️‍⚧️
        𒎏Wii 🏳️‍⚧️Sep 28, 2020

        I've used more timers less than 1 second or timeouts like 1.5 seconds

        What's the problem with sleep(1.5)? I still find that more natural than sleep(1500)

        Plus its so standard

        No it's not. C uses seconds, the linux command-line program sleep also uses seconds... There's lots of examples out there and milliseconds is far from common.

        The only two differences are:

        1. Seconds are the SI base unit.
        2. Seconds are within the orders of magnitude that humans can perceive.

        I'd say both of those are clearly benefits of using seconds.

        • PuruVJ
          PuruVJSep 28, 2020

          Well, you have a point.

          However having seconds measurement in a language that puts milliseconds as first class citizens would incur the cost of context switching.

          Thanks for the info

          • 𒎏Wii 🏳️‍⚧️
            𒎏Wii 🏳️‍⚧️Sep 28, 2020

            The context switching is precisely why I want this. If you're dealing with seconds in the backend but have to constantly switch to thinking in milliseconds for the frontend code, that's mental work I could spend thinking about the actual code.

Add comment