@time-provider/addon-idle
v0.1.1
Published
Time-Provider : Idle addon ~ Your single time interface for all your JavaScript / TypeScript projects.
Maintainers
Readme
Time-Provider ~ Idle Addon
Description
This is the Idle addon for Time-Provider.
It adds a scheduler.idle facade exposing the idle callback API (request, cancelled via dispose() on the returned handle), beside the scheduler.timers and scheduler.microtasks that core already provides.
Just like the plugin packages, this addon is tree-shakable.
It is split into a default (system/real-time) entry point and a deterministic one, so each import pulls in only the code it needs:
@time-provider/addon-idle- for a system (real time) Time-Provider created via@time-provider/core..scheduler.idle.requestpasses through to the realrequestIdleCallback, or throws a clear error when the host has no native equivalent (e.g. Safari) -cancelIdleCallbackitself stays an internal detail; cancel by callingdispose()on the handle.scheduler.idle.requestreturns.@time-provider/addon-idle/deterministic- for a deterministic Time-Provider (fixed/manual/sequential) created via@time-provider/core/deterministic. Requests made through.scheduler.idle.requeststay pending until a test declares the runtime idle via.scheduler.idle.drain().
Usage
import { createTimeProvider } from "@time-provider/core";
import { createTimeProvider as createDeterministicTimeProvider } from "@time-provider/core/deterministic";
import { plugin } from "@time-provider/plugin-native";
import { plugin as deterministicPlugin } from "@time-provider/plugin-native/deterministic";
import { addon } from "@time-provider/addon-idle";
import { addon as deterministicAddon } from "@time-provider/addon-idle/deterministic";
// System: real requestIdleCallback under the hood (or a clear error if not available)
const timeProvider = createTimeProvider.for(plugin).use(addon).create();
timeProvider.scheduler.idle.request(() => console.log("Idle!"));
// Deterministic: requests stay pending until you declare the runtime idle
const manual = createDeterministicTimeProvider
.for(deterministicPlugin)
.use(deterministicAddon)
.asManual()
.withInitialTime(0)
.create();
manual.scheduler.idle.request(() => console.log("Idle!"));
manual.scheduler.idle.drain(); // the idle callback runs hereSimulated idle periods
There is no such thing as a real idle period on a deterministic runtime - unlike a timeout,
nothing about elapsed simulated time says the runtime has spare capacity - so request() just
registers the callback under this addon's own tag in the runtime's shared due-heap. advance()/
clock reads never fire it on their own; only drain() does, by retrieving up to maxCount
pending requests (oldest first) directly through that tag - without scanning any other pending
timer/interval/recurring entry sharing the heap:
manual.scheduler.timers.once({ milliseconds: 50 }, () => console.log("Busy!"));
manual.scheduler.idle.request(() => console.log("Idle!"));
manual.clock.advance({ milliseconds: 50 }); // "Busy!" - the idle request is still pending
manual.scheduler.idle.drain(); // "Idle!"Omit maxCount to run everything currently pending, or pass it to cap how much idle work a
single idle period allows through:
manual.scheduler.idle.request(() => console.log("first"));
manual.scheduler.idle.request(() => console.log("second"));
manual.scheduler.idle.drain(1); // "first" - "second" stays pending for the next drainWith the compat addon
Compose @time-provider/addon-compat before this addon and its .compat facade also gets requestIdleCallback/cancelIdleCallback, delegating to request and to the handle's dispose(). They are declared as an optional compat? on WithIdleApi, since they are only there when both addons are composed.
License
MIT
