Event loop execution order
I’m studying how the Javascript event loop works for a future presentation, but I’ve come across an unexpected behavior with the information I have so far. Simply put, when I post a message to the worker, the execution of postmessage always occurs after the setTimeout..
script.js:
new Worker('worker.js').postMessage('');
setTimeout( () => {
const now = new Date().toISOString();
console.log(`setTimeout execution: ${now}`);
}, 0);
worker.js:
onmessage = function (event) {
const now = new Date().toISOString();
console.log(`Worker execution: ${now}`);
}
If you want to try it in the console by yourself:
const workerCode = `
self.onmessage = function (event) {
const now = new Date().toISOString();
self.postMessage("worker executed: " + now);
}`;
const blob = new Blob([workerCode], { type: 'application/javascript' });
const workerURL = URL.createObjectURL(blob);
const worker = new Worker(workerURL);
worker.onmessage = function (event) {console.log(event.data)};
worker.postMessage('');
setTimeout( () => {
const now = new Date().toISOString();
console.log(`setTimeout executed: ${now}`);
}, 0);
My question
Correct me if I’m wrong, but the event loop works in the following order:
- Execute all tasks in the call stack
- Execute all tasks in the micro task
- Execute a task in the macro task
- Render graphic/UI
If this is true, knowing that setTimeout is placed in the macro tasks queue, which is literally the last queue to be read, why is the postmessage executed after setTimeout? If during synchronous execution, it is placed in the queue (whatever that queue may be) before setTimeout?
What have I already tried?
I tried to put a delay, but this keeps happening even if setTimeout is delayed, so i believe the cause of this is not the fact that the worker is running in a parallel thread to the main one. Example:
setTimeout( () => {
const start = performance.now();
while (performance.now() - start < 1000) { };
const now = new Date().toISOString();
console.log(`Execution setTimeout: ${now}`);
}, 0);

