Skip to content

Instantly share code, notes, and snippets.

@peter-leonov
Last active April 6, 2020 18:25
Show Gist options
  • Save peter-leonov/9b202424390a364f1ed4f6c15c341ce8 to your computer and use it in GitHub Desktop.
Save peter-leonov/9b202424390a364f1ed4f6c15c341ce8 to your computer and use it in GitHub Desktop.
Pure JS event loop implementation with only timers working
// timer.js
function main(global) {
global.mySetTimeout(function () {
console.log("500ms");
}, 500);
global.mySetTimeout(function () {
console.log("100ms");
}, 100);
global.mySetTimeout(function () {
console.log("300ms begin");
global.mySetTimeout(function () {
console.log("300ms + 0m");
}, 0);
global.nextTick = function () {
console.log("nextTick");
};
console.log("300ms end");
}, 300);
global.mySetTimeout(function () {
console.log("1000ms");
global.exit();
}, 1000);
}
// timer.cpp
// platform code
function eventLoop(main) {
let exitFlag = false;
let timers = [];
const global = {
mySetTimeout(cb, delay) {
timers.push({
callback: cb,
dueDate: Date.now() + delay,
});
// …
},
exit() {
exitFlag = true;
throw "special"; // magic
},
};
main(global);
while (true) {
if (exitFlag == true) {
break;
}
const nextTimers = [];
for (const { callback, dueDate } of timers) {
if (dueDate <= Date.now()) {
try {
// enter the JS engine
callback();
// JS engine done with this portion of work
if (global.nextTick) {
// promises then() and catch() to be executed here
// kinda microtasks
global.nextTick();
global.nextTick = undefined;
}
// check promises
} catch {}
} else {
nextTimers.push({ callback, dueDate });
}
}
timers = nextTimers;
}
}
// glue-code.js.cpp
eventLoop(main);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment