const sleep = (delay) => ({ awaitable: 'setTimeout', args: [delay] });
function* createTask(name) {
let i = 0;
while (true) {
console.log('awaiting', name, i)
const result = yield sleep(1000 * Math.random());
console.log('result', name, i, result);
i++;
}
}
const eventQueue = [];
let abort = false;
const asyncs = {
'setTimeout': (args, cb) => {
setTimeout(() => cb(args[0] || 1), args[0] || 1);
}
}
let iter = 0;
function trampoline() {
const task = eventQueue.shift();
if (task) {
const { value, done } = task.fn.next(task.result);
const { awaitable, args } = value;
if (!done) {
if (asyncs[awaitable]) {
asyncs[awaitable](args, (result) => {
eventQueue.push({ fn: task.fn, result });
})
} else {
eventQueue.push({ fn: task.fn, result: null });
}
}
}
iter++;
if (!abort) setTimeout(trampoline, 0);
}
eventQueue.push({ fn: createTask('a'), args: [] });
eventQueue.push({ fn: createTask('b'), args: [] });
trampoline();