I have this small piece of example code:
//main.js const {Worker} = require("worker_threads"); const worker = new Worker("./background.js", {workerData: {}}); function loop() { console.log("main: 1234567890"); setTimeout(loop, 0) } loop();
And:
//background.js const {parentPort, workerData} = require("worker_threads"); function loop () { console.log("background: 1234567890"); setTimeout(loop, 0) } loop();
Run like so: node main.js
The output is this:
background: 1234567890 main: 1234567890 background: 1234567890 main: 1234567890 background: 1234567890 background: 1234567890 #etc
Sometimes several console.log()’s from one thread are called before any are called by the other. This is expected, and fine.
But is there any chance that a console.log() could be called in the middle of another console.log()? So for example, could this happen?
background: 123main: 12345456786789090
I haven’t observed it in my output, but I’d like to know from a canonical source that Workers/console.log() do not work that way in node.js.
Advertisement
Answer
console.log()
for primitives (non-objects) is thread-safe. So, in your particular example where you’re passing a string, that is safe and you won’t get mixed up output.
But, if you pass an object to console.log(obj)
and threads are in the process of modifying that object, then there can be issues before the object is turned into output and marshalled over to the logging output. This can even happen with just a single thread where you immediately modify the object on subsequent lines of code.
This apparently occurs because the conversion of the object to the console output is “lazy” and not immediate. This is probably an attempt to run this in parallel in order to minimize the performance impact of calls to console.log()
. I’ve seen this in real code and the work-around was to call console.log(JSON.stringify(obj))
rather than console.log(obj)
to remove any chance of an issue with the object being modified before it got lazily logged.