-
Notifications
You must be signed in to change notification settings - Fork 0
services track
io.track deduplicates in-flight requests at the run level: concurrent identical GETs share a single decoded envelope instead of each hitting the network and reparsing the body.
import io from 'double-meh';
const [a, b] = await Promise.all([
io.get('https://example.com/dup'),
io.get('https://example.com/dup')
]);
// one network call; a and b are the same decoded resultThe first caller of a key marks it in-flight and runs the request; later callers awaiting the same key receive the same resolved envelope — decoded once, not cloned and reparsed. Dedup is keyed by method + URL, so different keys never share.
const [a, b] = await Promise.all([
io.full.get('https://example.com/shared'),
io.full.get('https://example.com/shared')
]);
a === b; // true — one envelope object, decoded at the run levelTracking is GET-only, hard: track: true on a non-GET does nothing. Within GETs, track: false opts a request out, and io.track.theDefault — a boolean or a predicate (options) => boolean, default options => !options.transport — decides for requests that don't say. So GETs on a custom transport are not tracked unless they pass track: true.
stream: true requests are never deduped — each streaming caller gets its own response and body.
await Promise.all([
io.full.get('https://example.com/s', null, {stream: true}),
io.full.get('https://example.com/s', null, {stream: true})
]); // two independent responsestrack: 'wait' registers interest in a key without firing a request. The returned promise stays pending until a later real request (or io.adopt) for the same key lands, then resolves every waiter with that result. track: 'wait' on a non-trackable request (a non-GET, or a stream) throws a TypeError.
const waiter = io.get({url: 'https://example.com/w', track: 'wait'});
// nothing has been sent yet
const real = io.get('https://example.com/w'); // the real request fires
const [w, r] = await Promise.all([waiter, real]); // both resolve to the landed dataThese expose the in-flight registry directly:
-
io.track.fly(target)— get (creating if needed) the deferred for a target. -
io.track.flyByKey(key)— same, addressed by a raw key fromio.makeKey. -
io.track.isFlying(target)— the deferred if the key is currently in flight, elseundefined.
io.track.fly('https://example.com/soon'); // register interest by target
const pending = io.track.isFlying('https://example.com/soon');
if (pending) await pending.promise;io.adopt(target, source) fulfills a key from an externally issued response (a Promise<Response> or Response) instead of the network — it marks the key flying so a later real request does not also fire, resolves all waiters, and (when the cache is active and the request is cacheable) saves the GET. This is the basis of the code-forward handoff: a page can pre-register in-flight keys via fly and later feed their responses via adopt, so client hydration reuses server-issued data.
io.adopt('https://example.com/me', json({from: 'prelude'}));
const data = await io.get('https://example.com/me'); // no network — uses the adopted responseThe main entry attaches tracking for you. io.track.attach() / io.track.detach() toggle io.track.active and return io.
io.track.detach(); // disable dedup
io.track.attach(); // re-enableGuides
Concepts
Services
Modules
- fetch transport
- keys & URLs
- helpers
- records
- sse
- storage backends
- compression encoders
- Service Worker integration
Cookbook