-
-
Save ymqy/e2975bede2b69339c204d863c1b0894f to your computer and use it in GitHub Desktop.
Event loop
This file contains 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 <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: [] | |
... | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment