node.jsnode-worker-threads

Facing problem of making node worker thread promises


I am trying to make a test of offloading task to worker thread.

The workflow is quite simple, I have 100 promises of array, each promise will create a worker thread.

The main thread will pass the index to the worker thread, the worker thread will wait 1.5sec then return the index to main thread.

main.js:

const { Worker } = require("node:worker_threads");

(async () => {
  await Promise.all(
    Array.from(Array(100), (x, i) => i).map(
      (i) =>
        new Promise((resolve, reject) => {
          const worker = new Worker("./worker.js");
          worker.postMessage(i);
          worker.on("message", (event) => resolve(event));
          worker.on("error", reject);
          worker.on("exit", (code) => console.log(`worker ${code} exited`));
        })
    )
  )
    .then((results) => console.log(results))
    .catch((err) => console.log(err));
})();

worker.js

const { workerData, parentPort } = require("node:worker_threads");

const setTimeoutPromise = (ms) => {
  return new Promise(async (resolve, reject) => {
    await setTimeout(() => {
      resolve();
    }, ms);
  });
};

onmessage = async (index) => {
  console.log(`receive index: ${index}`);
  await setTimeoutPromise(1500);
  parentPort.postMessage(`worker ${index} return`);
};

But even the Promise.all haven't return result, all worker thread is exited and the application is done.

How can I wait all worker thread promises finish like simple promises does?


Solution

  • I think that this code just creates a variable called onmessage instead of assigning the listener

    onmessage = async (index) => {
      console.log(`receive index: ${index}`);
      await setTimeoutPromise(1500);
      parentPort.postMessage(`worker ${index} return`);
    };
    

    Try using this instead:

    parentPort.once('message', async (index) => {
      console.log(`receive index: ${index}`);
      await setTimeoutPromise(1500);
      parentPort.postMessage(`worker ${index} return`);
    });
    

    You can also use on instead of once if you want to listen for more than one message event