UNPKG

@v4fire/client

Version:

V4Fire client core library

149 lines (116 loc) 2.44 kB
/*! * V4Fire Client Core * https://github.com/V4Fire/Client * * Released under the MIT license * https://github.com/V4Fire/Client/blob/master/LICENSE */ /** * [[include:core/render/README.md]] * @packageDocumentation */ import { daemon, queue, add as addToQueue, TASKS_PER_TICK, DELAY } from 'core/render/const'; export * from 'core/render/const'; export * from 'core/render/interface'; let inProgress = false, isStarted = false; queue.add = function add<T = unknown>(...args: unknown[]): T { const res = addToQueue(...args); if (!isStarted) { run(); } return res; }; /** * Restarts the render daemon */ export function restart(): void { isStarted = false; inProgress = false; run(); } /** * Restarts the render daemon * (it runs on the next tick) */ export function deferRestart(): void { isStarted = false; inProgress = false; daemon.clearAll(); runOnNextTick(); } function run(): void { daemon.clearAll(); const exec = async () => { inProgress = true; isStarted = true; let time = Date.now(), done = TASKS_PER_TICK; for (let w = queue.values(), el = w.next(); !el.done; el = w.next()) { const val = el.value; if (done <= 0 || Date.now() - time > DELAY) { await daemon.idle({timeout: DELAY}); time = Date.now(); // eslint-disable-next-line require-atomic-updates done = TASKS_PER_TICK; } const w = val.weight ?? 1; if (done - w < 0 && done !== TASKS_PER_TICK) { continue; } const canRender = val.fn(); const exec = (canRender) => { if (Object.isTruly(canRender)) { done -= val.weight ?? 1; queue.delete(val); } }; if (Object.isPromise(canRender)) { const now = Date.now(); await canRender.then(exec); if (now - time > DELAY) { time = now; done += val.weight ?? 1; } } else { exec(canRender); } } if (!runOnNextTick()) { daemon.setImmediate(() => { inProgress = canProcessing(); isStarted = inProgress; if (inProgress) { runOnNextTick(); } }); } }; if (inProgress || queue.size >= TASKS_PER_TICK) { exec().catch(stderr); } else { daemon.setImmediate(() => exec().catch(stderr)); } } function canProcessing(): boolean { return Boolean(queue.size); } function runOnNextTick(): boolean { if (canProcessing()) { daemon.requestIdleCallback(run, {timeout: DELAY}); return true; } return false; }