svelte
Version:
Cybernetically enhanced web apps
49 lines (41 loc) • 1.01 kB
JavaScript
/** @import { TaskCallback, Task, TaskEntry } from '#client' */
import { raf } from './timing.js';
// TODO move this into timing.js where it probably belongs
/**
* @returns {void}
*/
function run_tasks() {
// use `raf.now()` instead of the `requestAnimationFrame` callback argument, because
// otherwise things can get wonky https://github.com/sveltejs/svelte/pull/14541
const now = raf.now();
raf.tasks.forEach((task) => {
if (!task.c(now)) {
raf.tasks.delete(task);
task.f();
}
});
if (raf.tasks.size !== 0) {
raf.tick(run_tasks);
}
}
/**
* Creates a new task that runs on each raf frame
* until it returns a falsy value or is aborted
* @param {TaskCallback} callback
* @returns {Task}
*/
export function loop(callback) {
/** @type {TaskEntry} */
let task;
if (raf.tasks.size === 0) {
raf.tick(run_tasks);
}
return {
promise: new Promise((fulfill) => {
raf.tasks.add((task = { c: callback, f: fulfill }));
}),
abort() {
raf.tasks.delete(task);
}
};
}