0

I need to run multiple parallel tasks (infinite loops) without blocking each other in node.js. I'm trying now to do:

const test = async () => {
  let a = new Promise(async res => {
    while (true) {
      console.log('test1')
    }
  })

  let b = new Promise(async res => {
    while (true) {
      console.log('test2')
    }
  })
}

test();

But it does not work, only 'test1' appears in the console. What am I doing wrong?

6
  • You can't run even a single infinite loop in the main nodejs thread (unless there's an await in the loop) and have nodejs function properly. Nodejs relies on its event loop being able to run. An infinite loop starves the event loop. Perhaps you should describe your real problem and we could advise on a better way to solve the real problem because this is not the way to solve it. Commented Apr 14, 2022 at 6:00
  • And, btw, wrapping synchronous code in an async function or in a promise does not help you in any way. Blocking synchronous code is still synchronous and blocking whether wrapped or not. Commented Apr 14, 2022 at 6:03
  • I'm also curious why you think the code would ever advance past the first infinite while loop? It's an infinite loop. In your code structure, the 2nd loop doesn't get to execute until the first one is done. Neither promises or async callbacks change that in any way. Commented Apr 14, 2022 at 6:06
  • FYI, there are worker threads in nodejs, but whether or not those are appropriate depends entirely upon what the actual, real problem is here. Commented Apr 14, 2022 at 6:12
  • This is currently an XY problem where you've asked about a possible solution and not described the real problem at all. Since the solution you asked about is a dead-end (not the right way to go) and you haven't described the real problem, we can't help you with an good solution to your actual problem. Please try not to ask XY questions here as it just handicaps our ability to help you with the real problem. Commented Apr 14, 2022 at 6:17

1 Answer 1

3

You can't. You need to stop thinking in loops but start thinking in event loop instead.

There are two functions that can schedule functions to run in the future that can be used for this: setTimeout() and setInterval(). Note that in Node.js there is also setImmediate() but I suggest you avoid using it until you really know what you are doing because setImmediate() has to potential to block I/O.

Note that neither setTimeout() not setImmediate() are Promise aware.

The minimal code example that does what you want would be something like:

const test = () => {
  setInterval(() => {
      console.log('test1')
    },
    10 // execute the above code every 10ms
  )

  setInterval(() => {
      console.log('test2')
    },
    10 // execute the above code every 10ms
  )
}

test();

Or if you really want to run the two pieces of code as fast as possible you can pass 0 as the timeout. It won't run every 0ms but just as fast as the interpreter can. The minimal interval differs depending on OS and how busy your CPU is. For example Windows can run setInterval() down to every 1ms while Linux typically won't run any faster than 10ms. This is down to how fast the OS tick is (or jiffy in Linux terminology). Linux is a server oriented OS so sets its tick bigger to give it higher throughput (each process gets the CPU for longer thus can finish long tasks faster) while Windows is a UI oriented (some would say game oriented) OS so sets its tick smaller for smoother UI experience.

To get something closer to the style of code you want you can use a promisified setTimeout() and await it:

function delay (x) {
  return new Promise((done, fail) => setTimeout(done,x));
}

const test = async () => {
  let a = async (res) => {
    while (true) {
      console.log('test1')
      await delay(0) // this allows the function to be async
    }
  }

  let b = async (res) => {
    while (true) {
      console.log('test2')
      await delay(0) // this allows the function to be async
    }
  }

  a();
  b();
}

test();

However, this is no longer the minimal possible working code, though not by much.

Note: After writing the promisified example above it suddenly reminded me of the programming style on early cooperative multitasking OSes. I think Windows3.1 did this though I never wrote anything on it. It reminds me of MacOS Classic. You had to periodically call the WaitNextEvent() function to pass control of the CPU back to the OS so that the OS can run other programs. If you forgot to do that (or your program gets stuck in a long loop with no WaitNextEvent() call) your entire computer would freeze. This is exactly what you are experiencing with node where the entire javascript engine "freezes" and executes only one loop while ignoring other code.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.