DataLoader Batching
Hard · Async
In an API, loading 50 posts and then each post's author one by one causes 51 database queries: the "N+1 problem". Facebook's DataLoader fixes it: load(key) calls made in the same tick are collected and sent to ONE call of a batch function.
Implement class DataLoader:
- constructor(batchFn, options): batchFn(keys) returns a Promise of an array with one result per key, in the same order. options.maxBatchSize (optional) limits how many keys go into one call.
- load(key) returns a Promise for the value. The first load of a new batch schedules the dispatch with queueMicrotask or setTimeout(..., 0), so every load made synchronously before that ends up in the same batch. Keys are sent in the order they were first requested. With more than maxBatchSize keys, split them into several calls of at most maxBatchSize keys, in order.
- Cache: loading a key that was loaded before returns the same Promise, so a key is not sent again. clear(key) removes a key from the cache.
- If the result for a key is an Error instance, only that key's Promise rejects with it (and it stays cached, like in the real DataLoader).
- If batchFn rejects, or does not return an array with exactly one result per key, every key of that call rejects (for the length problem use an Error with the message "Batch function must return one result per key"), and those keys are removed from the cache so a later load tries again.
The driver runLoader(config, ticks) is already written. It builds a fake async batch function that records every call and looks keys up in config.data (a missing key gives new Error("not found: <key>")). Calls whose index is in config.failBatches reject with "database down", and calls in config.shortBatches return one result too few. Each tick is a list of ["load", key] and ["clear", key] operations run synchronously; the driver waits for the loads of a tick to settle before starting the next one. It returns { calls, results }, where results has one entry per load: the value or "Error: <message>".
Next: Streaming CSV Parser