Created
August 22, 2018 09:23
-
-
Save philipszdavido/0317ccd9fef11e3384a02ecd0f88b3e4 to your computer and use it in GitHub Desktop.
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
let timers = [] // eg. setTimeout(...), setInterval(...) | |
let pending_callbacks = [] | |
let idle = [] // eg. requestIdleCallback(...) | |
let prepare = [] | |
let poll = [] //eg. HTTP conns, Socket conns, file ops | |
let check = [] // eg. setImmediate(...) | |
let close = [] // eg. socket.on('close',()=>{...}) | |
let exit=[] | |
const log = console.log | |
var now = null | |
function removeFromArray(arr, index) { | |
// perf: array.pop is faster than array.splice! | |
if (index >= arr.length - 1) { | |
arr.pop(); | |
} else { | |
arr.splice(index, 1); | |
} | |
} | |
function isEmpty(arr) { | |
return (arr.length <= 0) ? true : false | |
} | |
function is_loop_alive(){ | |
if( | |
isEmpty(timers) && | |
isEmpty(pending_callbacks)&& | |
isEmpty(idle)&& | |
isEmpty(prepare)&& | |
isEmpty(poll)&& | |
isEmpty(check)&& | |
isEmpty(close) | |
){ | |
return false | |
}else{ | |
return true | |
} | |
} | |
function call_exit(){ | |
run_a_phase(exit) | |
} | |
function checkTimers(timers) { | |
for (let i = 0; i < timers.length; i++) { | |
const { callback, ms } = timers[i] | |
const _now = Date.now() | |
if ((ms + now) <= _now) { | |
return true | |
} | |
} | |
return false | |
} | |
function waitForCallbacks(){ | |
/* poll will try to wait a bit, but with certain conditions. | |
* If there is any task pending in check queue, pending queue or closing callbacks queue (idle handlers queue as well), it will | |
* wait for zero milliseconds. | |
*/ | |
} | |
function run_a_phase(phase){ | |
for (let i = 0; i < phase.length; i++) { | |
phase[i]() | |
removeFromArray(phase, i) | |
} | |
} | |
const _setTimeout = function(callback, ms) { | |
timers.push({ | |
ms, | |
callback | |
}) | |
timers.sort((a,b)=>a-b) | |
} | |
const _setImmediate = function(cb) { | |
check.push(cb) | |
} | |
const socket_on_close = function(cb) { | |
close.push(cb) | |
} | |
/** phase functions here */ | |
function run_timers_phase() { | |
if(!now){ | |
now = Date.now() | |
} | |
//const now = Date.now() | |
//while (timers.length > 0) { | |
for (let i = 0; i < timers.length; i++) { | |
const { callback, ms } = timers[i] | |
const _now = Date.now() | |
if ((ms + now) <= _now) { | |
callback() | |
removeFromArray(timers, i) | |
} | |
} | |
//} | |
} | |
function run_pending_callbacks_phase() { | |
run_a_phase(pending_callbacks) | |
} | |
function run_idle_phase() { | |
run_a_phase(idle) | |
} | |
function run_prepare_phase() { | |
run_a_phase(prepare) | |
} | |
function run_poll_phase() { | |
const SYSTEM_HARD_LIMIT = 100 | |
//If the poll queue is not empty | |
if (!isEmpty(poll)) { | |
//iterate through its queue of callbacks executing them synchronously | |
for (var index = 0; index < poll.length; index++) { | |
poll[index](); | |
removeFromArray(poll, index) | |
if (index == SYSTEM_HARD_LIMIT) { | |
break; | |
} | |
} | |
} | |
//If the poll queue is empty | |
else { | |
//If scripts have been scheduled by setImmediate() , | |
if (!isEmpty(check)) { | |
//end the poll phase and continue to the check phase to execute those scheduled scripts | |
return run_check_phase() | |
} | |
//If scripts have not been scheduled by setImmediate() | |
else { | |
//wait for callbacks to be added to the queue, then execute them immediately. | |
waitForCallbacks() | |
} | |
} | |
//check for timers whose time thresholds have been reached. | |
if(checkTimers(timers)){ | |
run_timers_phase() | |
} | |
} | |
function run_check_phase() { | |
run_a_phase(check) | |
} | |
function run_close_phase() { | |
run_a_phase(close) | |
} | |
function main() { | |
while(is_loop_alive()){ | |
run_timers_phase() | |
run_pending_callbacks_phase() | |
run_idle_phase() | |
run_prepare_phase() | |
run_poll_phase() | |
run_check_phase() | |
run_close_phase() | |
} | |
call_exit() | |
} | |
/*setTimeout(()=>{ | |
log('1000 ms') | |
},1000) | |
setTimeout(()=>{ | |
log('1000000 ms') | |
},10) | |
run_timers_phase() | |
*/ | |
_setTimeout(() => { | |
log('0 ms') | |
},0) | |
_setImmediate(()=>{log('ImmediateI')}) | |
_setTimeout(() => { | |
log('1 ms') | |
}, 1) | |
_setTimeout(() => { | |
log('100 ms') | |
}, 100) | |
_setTimeout(() => { | |
log('200 ms') | |
}, 200) | |
_setImmediate(()=>{log('ImmediateII')}) | |
_setTimeout(() => { | |
log('300 ms') | |
}, 300) | |
_setTimeout(() => { | |
log('400 ms') | |
}, 400) | |
main() | |
return | |
setTimeout(() => { | |
log('0 ms') | |
},0) | |
setImmediate(()=>{log('ImmediateI')}) | |
setTimeout(() => { | |
log('1 ms') | |
}, 1) | |
setTimeout(() => { | |
log('2 ms') | |
}, 2) | |
setTimeout(() => { | |
log('3 ms') | |
}, 3) | |
setTimeout(() => { | |
log('100 ms') | |
}, 100) | |
setTimeout(() => { | |
log('200 ms') | |
}, 200) | |
setImmediate(()=>{log('ImmediateII')}) | |
setTimeout(() => { | |
log('300 ms') | |
}, 300) | |
setTimeout(() => { | |
log('400 ms') | |
}, 400) | |
/* | |
0 ms | |
1 ms | |
ImmediateI | |
ImmediateII | |
100 ms | |
200 ms | |
300 ms | |
400 ms | |
*/ | |
return | |
/*0 ms | |
ImmediateI | |
ImmediateII | |
100 ms | |
200 ms | |
300 ms | |
400 ms | |
*/ | |
//run_timers_phase() | |
/* | |
function run_timers_phase() { | |
const now = Date.now() | |
while (timers.length > 0) { | |
for (let i = 0; i < timers.length; i++) { | |
const { callback, ms } = timers[i] | |
const _now = Date.now() | |
if ((ms + now) <= _now) { | |
callback() | |
removeFromArray(timers, i) | |
} | |
} | |
} | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment