Last active
June 28, 2024 16:54
-
-
Save DmitrySoshnikov/26e54990e7df8c3ae7e6e149c87883e4 to your computer and use it in GitHub Desktop.
Event loop
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Event loop. | |
* | |
* Read details here: | |
* http://dmitrysoshnikov.com/ecmascript/javascript-the-core-2nd-edition/#job | |
* | |
* by Dmitry Soshnikov <[email protected]> | |
*/ | |
/** | |
* Call-stack. | |
*/ | |
const stack = []; | |
/** | |
* Jobs queue. | |
*/ | |
const jobs = []; | |
/** | |
* Event loop spins, and checks whether something was enqueued. | |
* If the execution stack is empty, it picks a job, and executes it. | |
* A job can enqueue other jobs. | |
*/ | |
setInterval(function eventLoop() { | |
console.log( | |
`\n Analyzing jobs queue:`, | |
`[${jobs.map(job => job.name).join(', ')}]\n` | |
); | |
// Something is on the stack, can't run jobs yet. | |
if (stack.length) { | |
return; | |
} | |
// Nothing to run. | |
if (!jobs.length) { | |
return; | |
} | |
// Pick up the next job, and put it onto the stack. | |
const job = jobs.shift(); | |
run(job); | |
}, /* Spin! */ 1000); | |
/** | |
* Executes the code. | |
*/ | |
function run(activation) { | |
// Emulate stack "push-pop". | |
stack.push(activation); | |
console.log( | |
`Running "${activation.name}", stack:`, | |
`[${stack.map(context => context.name).join(', ')}]` | |
); | |
// Run the code. | |
activation(); | |
stack.pop(activation); | |
} | |
/** | |
* The `postponeCall` waits for the ms, and then | |
* enqueues the activation as a job. | |
*/ | |
function postponeCall(runnable, ms) { | |
setTimeout(() => jobs.push(runnable), ms); | |
} | |
// ----------------------------------------------------------------------------- | |
// Tests. | |
function one() { | |
run(two); | |
} | |
function two() { | |
postponeCall(three, 10); | |
} | |
function three() { | |
postponeCall(four, 10); | |
postponeCall(five, 20); | |
run(six); | |
} | |
function four() { | |
return; | |
} | |
function five() { | |
return; | |
} | |
function six() { | |
return; | |
} | |
// Go! | |
(function start() { | |
// Enqueue the first call, which will run other functions, | |
// and enqueue other postponed calls. | |
postponeCall(one, 100); | |
})(); | |
// ----------------------------------------------------------------------------- | |
// Results: | |
/* | |
Analyzing jobs queue: [one] | |
Running "one", stack: [one] | |
Running "two", stack: [one, two] | |
Analyzing jobs queue: [three] | |
Running "three", stack: [three] | |
Running "six", stack: [three, six] | |
Analyzing jobs queue: [four, five] | |
Running "four", stack: [four] | |
Analyzing jobs queue: [five] | |
Running "five", stack: [five] | |
Analyzing jobs queue: [] | |
Analyzing jobs queue: [] | |
Analyzing jobs queue: [] | |
... | |
*/ |
Good example. But I am confused "CallStack" between Event Loop and JS Engine. I thought "CallStack" is part of the JS engine, but it is in Event Loop in this example. Are they same things?
Good example. But I am confused "CallStack" between Event Loop and JS Engine. I thought "CallStack" is part of the JS engine, but it is in Event Loop in this example. Are they same things?
In my option, event loop is provide by host environment, will check is JS engine call stack empty or not, when the stack is empty, event loop will put the job to the call stack.
Great, thank you Dmitry! ๐
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
๐