Use BatchLoader (with SyncLoader under the hood) to run many HTTP requests, cap concurrency, and coordinate a single completion or failure path. Handlers let you validate/transform each item, and a shared context makes results accessible by id.
- Throughput: parallelize requests with a safe concurrency cap.
- Determinism: each item is tracked by a unique
id. - Coordination: a single
onLoadoronFailwhen the batch completes. - Flexibility: per-item handlers for parsing, storage, and validation.
Returns:
awaitAll:true→results: { [id]: value }awaitAll:false→results: Promise<any>[]
const { sync, results } = await net.batch.run(
[
{ id: "cfg", url: "/config.json", opts: { format: "full" } },
{ id: "lang", url: "/i18n/en.json", opts: { format: "full" } },
{ id: "ping", url: "/health", opts: { format: "full" } },
],
// onLoad: fires when ALL items have completed (success or fail). If any failed and an onFail exists, onFail will run instead.
(prepend, last) => {
// prepend = { context, trigger, controller }
console.log("✅ done:", Object.keys(prepend.context));
},
// onFail: fires if ANY handler returned false (see failure semantics below)
(prepend, last) => {
console.warn("⚠️ one or more failed", { trigger: prepend.trigger });
},
{ awaitAll: true, limit: 8 }
);
// When awaitAll: true, `results` is a map of { id → handler result }.
// You can also read the shared context at any time:
const cfg = net.batch.get("cfg");Item schema
{
id: "unique-id", // required
method: "get" | "post", // defaults to "get"
url: "/path" | "https://…", // required
data: {…}, // request body for POST (optional)
opts: { format: "full" }, // per-request HTTP options
handler: (res) => any // optional transform/validation
}- Only a handler that returns
falsemarks that item as failed. - The default batch handler (
batchStatus) will store the response and automatically treat!res.okas failure. - For raw success values, return anything other than
false(includingundefined).
Edge case: if your API legitimately returns the literal JSON value
false, don’t propagate it directly as the handler’s return value. Wrap it:
handler: (res) => (res.body === false ? { ok: true, body: false } : res)Cap parallelism with the limit option:
await net.batch.run(loadList, onLoad, onFail, { awaitAll: true, limit: 4 });Requests are queued and executed using a lightweight limiter; set a sensible value (e.g., 4–16) to avoid server or browser saturation.
- Shared context: all stored outputs live under
prepend.context[id]during callbacks, and are accessible later vianet.batch.get(id). resultsmap: whenawaitAll: true, the return value includesresults[id]for each item.- Custom storage: if you use a custom batch handler that doesn’t store automatically, write to
obj.context[id]inside your handler.
const { results } = await net.batch.run([
{ id: "a", url: "/a.json", opts:{ format: "full" } },
{ id: "b", url: "/b.json", opts:{ format: "full" } },
]);
console.log(results.a, results.b);
console.log(net.batch.get("a")); // same value if using default storageFire handlers as responses arrive, and coordinate completion with SyncLoader:
const { sync } = await net.batch.run(loadList, onLoad, onFail, { awaitAll: false, limit: 8 });
// Option A: callbacks (onLoad/onFail) will run when all required items have finished.
// Option B: poll the sync state (e.g., in a UI loop)
const tick = setInterval(() => {
if (sync.loaded()) { // all done
clearInterval(tick);
console.log("success?", sync.success()); // true if no failures
}
}, 100);In streaming mode, prefer reading from the shared
context[id]as items complete.
Batch behavior can be tuned globally per batch instance.
batchStatus(obj, id, handler)(default) — stores the response, and marks failure if!res.ok.batchStore(obj, id, handler)— stores the response regardless of status; never fails unless yourhandlerreturnsfalse.batchNone(obj, id, handler)— no automatic storage; yourhandlercontrols everything. Returnfalseto fail.
// Apply to the current BatchLoader instance (affects subsequent runs)
net.batch.setBatchHandler(net.batch.batchStore); // always store
// or
net.batch.setBatchHandler(false); // use batchNone
// Provide default fetch options for all items in this batch context
net.batch.setFetchOpts({ format: "full" });// Normalize API responses into a common shape
function normalize(obj, id, handler) {
return (res) => {
const body = res.body ?? res; // handle format: 'body' or 'full'
if (body?.error) return false; // fail this item
const out = { data: body?.data ?? body, at: Date.now() };
obj.context[id] = out; // store yourself if using batchNone
return out; // returned value becomes results[id]
};
}
net.batch.setBatchHandler(normalize);
await net.batch.run([
{ id: "one", url: "/api/one", opts:{ format: "full" } },
{ id: "two", url: "/api/two", opts:{ format: "full" } },
]);- Allowed
methodvalues:getandpost(invalid values throw). - Each item must include a unique
idand aurl. - Duplicate IDs or missing fields throw clear errors.
await net.batch.run([
{ id: "dup", url: "/a" },
{ id: "dup", url: "/b" }, // ❌ throws: duplicate ID
]);- Config+lang bootstrap: load
/config.jsonand/i18n/en.jsontogether, render UI when both arrive. - Health fan‑out: ping several microservices and mark the panel red if any fail.
- Asset manifests: fetch multiple manifests, merge into a single registry before continuing.
- Progress UI: use
awaitAll:falseand a polling loop to update a progress bar as each ID completes.
- Prefer
format: "full"while developing to inspect{ ok, status, body }in handlers. - Surface endpoint, status, and a small body excerpt in logs.
- In
onFail, theprepend.controller.failmap contains the IDs that failed.
(prepend) => {
const failed = Object.keys(prepend.controller.fail);
console.warn("batch failed: ", failed);
}- Batch never completes → Ensure every handler returns something (not a never‑resolving promise). Use
awaitAll:trueto collect results deterministically. - False‑as‑failure → Wrap legitimate boolean
falseresults to avoid being treated as failure. - Unexpected body parsing → Set
opts.format: "raw"and parse yourself when downloading binary. - Too many open requests → Lower
limitto apply back‑pressure.
- HTTP_GUIDE.md — request/response options used inside each item.
- CORE_API_BATCH_LOADER.md — deep API surface and return shapes.
- CORE_API_SYNC_LOADER.md — coordinator semantics.