Skip to content

Instantly share code, notes, and snippets.

@victorporof
Last active May 30, 2022 06:25
Show Gist options
  • Save victorporof/f8bab8eaf12231366056d6c00bd1ff55 to your computer and use it in GitHub Desktop.
Save victorporof/f8bab8eaf12231366056d6c00bd1ff55 to your computer and use it in GitHub Desktop.
Async Stack Tagging API (Recurring)
/* --- Userland --- */
function makeUpdate(i) {
return function someUpdate() {
console.trace(`completeUpdate: update ${i}`);
};
}
function businessLogic() {
scheduler.scheduleTask("foo", [makeUpdate(1), makeUpdate(2), makeUpdate(3)]);
scheduler.scheduleTask("bar", [makeUpdate(4), makeUpdate(5)]);
}
businessLogic();
scheduler.scheduleWorkLoop();
/* --- Framework --- */
function makeTask(id, name, updates) {
return {
performNextUpdate() {
console.info(`Performing next update within task '${name}'.`);
const f = updates.shift();
console.startAsyncTask(id);
f();
console.finishAsyncTask(id);
if (updates.length) {
console.info(`Task '${name}' has ${updates.length} updates remaining.`);
return false;
}
console.info(`Task '${name}' finished, no updates remaining here.`);
console.cancelAsyncTask(id);
return true;
},
};
}
function makeScheduler() {
const tasks = [];
function workLoop(deadline) {
console.info(`Started new work loop.`);
while (deadline.ticksRemaining() > 0 && tasks.length) {
const task = tasks[0];
const finished = task.performNextUpdate();
if (finished) {
tasks.shift();
}
}
if (tasks.length) {
console.warn("Exceeded deadline but not finished, yielding.");
fakeRequestIdleCallback(workLoop);
return;
}
console.info("Work loop finished, no tasks remaining here.");
}
return {
scheduleTask(name, updates) {
const id = console.scheduleAsyncTask(name, true);
tasks.push(makeTask(id, name, updates));
console.info(`Scheduld task '${name}' with ${updates.length} updates.`);
},
scheduleWorkLoop() {
fakeRequestIdleCallback(workLoop);
},
};
}
const scheduler = makeScheduler();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Async Tasks API</title>
</head>
<body>
<script src="runtime.js"></script>
<script src="framework.js"></script>
<script src="async-stack-tagging-recurring.js"></script>
</body>
</html>
/* --- Runtime --- */
// Something akin to requestIdleCallback, but deterministic.
const BUDGET = 2;
function fakeRequestIdleCallback(cb) {
function makeDeadline() {
let ticks = BUDGET;
return {
ticksRemaining() {
return ticks--;
},
};
}
setTimeout(cb, 1000, makeDeadline());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment