Skip to content

Instantly share code, notes, and snippets.

@bhuvanesh-hotstar
Last active May 28, 2024 05:52
Show Gist options
  • Save bhuvanesh-hotstar/70cd5c6c0a988198ccd45f34d8b06a19 to your computer and use it in GitHub Desktop.
Save bhuvanesh-hotstar/70cd5c6c0a988198ccd45f34d8b06a19 to your computer and use it in GitHub Desktop.
Task Generator Util
const yieldToMain = () =>
new Promise((resolve) => {
requestAnimationFrame(() => {
setTimeout(resolve);
});
});
class Task {
state = "IDLE";
constructor(runnable, options) {
this.runnable = runnable;
this.options = options;
}
abort() {
this.state = "ABORTED";
}
async run() {
const { state: initialState } = this;
if (initialState === "ABORTED") {
throw new Error("cannot run aborted task");
} else if (initialState === "COMPLETED") {
throw new Error("cannot re-run completed task");
}
this.state = "RUNNING";
const { options, runnable } = this;
let iteratorValue;
try {
while (true) {
const { state } = this;
if (!(state === "RUNNING")) {
break;
}
const iteratorResult = runnable.next(iteratorValue);
iteratorValue = await iteratorResult.value;
if (options?.callback) {
options.callback(iteratorValue);
}
if (iteratorResult.done) {
this.state = "COMPLETED";
break;
}
}
} finally {
if (options?.onFinished) {
options.onFinished({ state: this.state });
}
}
}
}
// Sample usage
const doSomeTask = (id) => {
console.log(`task ${id} is done`);
};
const abortIfTheTaskRunsMoreThanASec = (task) => {
setTimeout(() => {
task.abort();
}, 1000);
};
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const task = new Task(
(function* () {
doSomeTask(1);
yield yieldToMain();
yield wait(500);
doSomeTask(2);
yield wait(500);
doSomeTask(3);
})(),
{
onFinished: () => console.log("finished before running task 3"),
}
);
task.run();
abortIfTheTaskRunsMoreThanASec(task);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment