const args = process.argv.slice(2)
if (args.length == 0) {
console.error("Error: missing event loop arg");
process.exit(1)
}
const which = args[0]
/*
* Call stack pushes functions onto the stack and executes
* the one on the end each event loop
* So in this example the stack goes like this
* foo1
* foo1 console.log
* foo1
* foo1 bar1
* foo1
* foo1 baz1
* foo1
* - empty
*/
if (which == 1) {
const bar1 = () => console.log('stack: bar1')
const baz1 = () => console.log('stack: baz1')
const foo1 = () => {
console.log('stack: foo1') // 2
bar1() // 3
baz1() // 4
}
foo1() // 1
}
/*
* setTimeout timers are run in an IO thread and their callbacks
* are put into the Message Queue which only is processed after
* the timer or IO is complet and the Call Stack is empty
* foo2
* foo2 console.log
* foo2
* foo2 setTimeout
* foo2
* foo2 baz2
* foo2
* bar2
* bar2console.log
* bar2
*/
if (which == 2) {
const bar2 = () => console.log('setTimeout: bar2')
const baz2 = () => console.log('stack: baz2')
const foo2 = () => {
console.log('stack: foo2') // 2
setTimeout(bar2, 0) // 4
baz2() // 3
}
foo2() // 1
}
/*
* ES6 introduced the Job Queue allows us to process async
* results as soon as possible
* CS foo3
* CS foo3 console.log
* CS foo3
* CS foo3 setTimeout
* CS foo3 new Promise
* CS foo3 new Promise console.log
* CS foo3 new Promise resolve
* CS foo3 new Promise
* CS foo3
* CS foo3 baz3
* CS foo3
* JQ resolve => console.log
* MQ bar3
*/
if (which == 3) {
const bar3 = () => console.log('setTimeout: bar3')
const baz3 = () => console.log('stack: baz3')
const foo3 = () => {
console.log('stack: foo3') // 2
setTimeout(bar3, 0) // 8
new Promise((resolve) => { // 3
console.log("stack: new Promise setup") // 4
resolve('resolve from promise: should be right after baz, before bar') // 5
}).then(resolve => console.log(`then: ${resolve}`)) // 7
baz3() // 6
}
foo3() // 1
}
/*
* process.nextTick will run a function at the end of the current
* tick and before the next one, and before the queues are processed
* process.nextTick // callback
* foo4
* foo4 console.log
* foo4
* foo4 setTimeout
* foo4
* foo4 new Promise
* foo4 new Promise resolve
* foo4
* foo4 baz4
* foo4
* console.log("next tick") // nexTick
* resolve => console.log // Promise resolve callback
* bar4 // setTimeout
*/
if (which == 4) {
process.nextTick(() => { // 1
console.log("process.nextTick") // 7
})
const bar4 = () => console.log('setTimout: bar4')
const baz4 = () => console.log('stack: baz4')
const foo4 = () => {
console.log("stack: foo4") // 3
setTimeout(bar4, 0) // 9
new Promise((resolve, reject) => { // 4
console.log("stack: new Promise")
resolve('res4') // 5
}).then(resolve => console.log(`then: ${resolve}`)) // 8
baz4() // 6
}
foo4() // 2
}
/*
* setImmediate is like setTimeout 0
*/
if (which == 5) {
process.nextTick(() => {
console.log("process.nextTick")
})
// this runs in the next tick and is essentially the
// same as setTimeout with 0
// running this several times will show them appearing
// back and forth in a race condition
setImmediate(() => {
console.log("setImmediate")
})
const bar5 = () => console.log('setTimeout: bar5')
const baz5 = () => console.log('stack: baz5')
const foo5 = () => {
console.log("stack: foo5")
setTimeout(bar5, 0)
new Promise((resolve, reject) => {
console.log("stack: new Promise")
resolve('res5')
}).then(resolve => console.log(`then: ${resolve}`)) // 8
baz5()
}
foo5()
}