Executing the code below randomly either prints "DONE" or not, why does it happen?
How do I make it go to the console.log("DONE");
line every time.
const {Worker, isMainThread, parentPort} = require('node:worker_threads');
async function main() {
if (isMainThread) {
const worker = new Worker(__filename);
let resultResolve = null;
let resultPromise = new Promise(resolve => resultResolve = resolve);
worker.on('message', (msg) => resultResolve(msg));
while (await resultPromise != null) {
resultPromise = new Promise(resolve => resultResolve = resolve);
}
console.log("DONE");
} else {
for (let i = 0; i < 10000; i++) {
parentPort.postMessage(i);
}
parentPort.postMessage(null);
}
}
main();
My guess is that the race happens when the worker exits and either the main thread event loop makes it to the await resultPromise
line before that or not.
UPDATE 1
I am trying to have an async generator yielding values produced by a thread worker.
A more meaningful example would be:
const {Worker, isMainThread, parentPort} = require('node:worker_threads');
async function* fooGenerator() {
const worker = new Worker(__filename);
let resultResolve = null;
let resultPromise = new Promise(resolve => resultResolve = resolve);
worker.on('message', (msg) => resultResolve(msg));
let result = null;
while ((result = await resultPromise) != null) {
resultPromise = new Promise(resolve => resultResolve = resolve);
yield result;
}
}
async function main() {
if (isMainThread) {
for await (let value of fooGenerator());
console.log("DONE");
} else {
for (let i = 0; i < 10000; i++) {
parentPort.postMessage(i);
}
parentPort.postMessage(null);
}
}
main();
UPDATE 2
Adding setInterval
doesn't solve the problem. It still won't print "DONE".
const {Worker, isMainThread, parentPort} = require('node:worker_threads');
async function main() {
if (isMainThread) {
setInterval(() => {}, 1000);
const worker = new Worker(__filename);
let resultResolve = null;
let resultPromise = new Promise(resolve => resultResolve = resolve);
worker.on('message', (msg) => resultResolve(msg));
while ((await resultPromise) != null) {
resultPromise = new Promise(resolve => resultResolve = resolve);
}
console.log("DONE");
} else {
for (let i = 0; i < 10000; i++) {
parentPort.postMessage(i);
}
parentPort.postMessage(null);
}
}
main();