Skip to content

Instantly share code, notes, and snippets.

@DmitrySoshnikov
Last active December 14, 2023 23:23
Show Gist options
  • Star 33 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save DmitrySoshnikov/26e54990e7df8c3ae7e6e149c87883e4 to your computer and use it in GitHub Desktop.
Save DmitrySoshnikov/26e54990e7df8c3ae7e6e149c87883e4 to your computer and use it in GitHub Desktop.
Event loop
/**
* Event loop.
*
* Read details here:
* http://dmitrysoshnikov.com/ecmascript/javascript-the-core-2nd-edition/#job
*
* by Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
*/
/**
* 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: []
...
*/
@IegorT
Copy link

IegorT commented Dec 7, 2017

Clear example
image

@yanghl22
Copy link

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?

@genshinw
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment