blob: c7e74c2986a9e6d19a3332aa33a9b21500b35736 [file] [edit]
class StepScheduler {
constructor(syncCallback, asyncCallback, params) {
this._syncCallback = syncCallback;
this._asyncCallback = asyncCallback;
this._params = params;
}
start() {
return new Promise((resolve) => {
if (this._params.waitBeforeSync)
setTimeout(() => this._scheduleCallbacks(resolve), this._params.waitBeforeSync);
else
this._scheduleCallbacks(resolve);
});
}
}
class RAFStepScheduler extends StepScheduler {
_scheduleCallbacks(resolve) {
requestAnimationFrame(() => this._syncCallback());
requestAnimationFrame(() => {
setTimeout(() => {
this._asyncCallback();
setTimeout(resolve, 0);
}, 0);
});
}
}
class AsyncRAFStepScheduler extends StepScheduler {
static mc = new MessageChannel();
_scheduleCallbacks(resolve) {
let gotTimer = false;
let gotMessage = false;
let gotPromise = false;
const tryTriggerAsyncCallback = () => {
if (!gotTimer || !gotMessage || !gotPromise)
return;
this._asyncCallback();
setTimeout(resolve, 0);
};
requestAnimationFrame(async () => {
await this._syncCallback();
gotPromise = true;
tryTriggerAsyncCallback();
});
requestAnimationFrame(() => {
setTimeout(async () => {
await Promise.resolve();
gotTimer = true;
tryTriggerAsyncCallback();
});
AsyncRAFStepScheduler.mc.port1.addEventListener(
"message",
async function () {
await Promise.resolve();
gotMessage = true;
tryTriggerAsyncCallback();
},
{ once: true }
);
AsyncRAFStepScheduler.mc.port1.start();
AsyncRAFStepScheduler.mc.port2.postMessage("speedometer");
});
}
}
export const STEP_SCHEDULER_LOOKUP = {
__proto__: null,
raf: RAFStepScheduler,
async: AsyncRAFStepScheduler,
};