All questions

Idle Task Scheduler

Premium

Idle Task Scheduler

You have 10,000 small jobs to run — parse rows, warm caches, build an index. Do them all in one loop and the main thread locks for a second: no scrolling, no clicks, a frozen page. The fix is time-slicing: run jobs in short bursts, and between bursts yield control back to the browser so it can paint a frame and handle input. This is exactly how React's scheduler and requestIdleCallback keep heavy work from janking the UI.

Implement taskSchedulerIdle(options) — a cooperative scheduler that runs a queue in time-budgeted slices, yielding between them. See MDN: requestIdleCallback.

Signature

function taskSchedulerIdle({ timeSlice, now, schedule, onDrain }) {
  return { add, clear, size, isRunning };
}

Examples

const s = taskSchedulerIdle({ timeSlice: 5 });
for (const row of hugeList) s.add(() => index(row));
// runs ~5ms of tasks, yields to the browser, resumes next tick, ... until done
const cancel = s.add(() => expensive());
cancel(); // remove it if it hasn't run yet

Notes

  • Slice by a time budget — within a slice, keep running tasks while now() - sliceStart < timeSlice; when the budget is spent, stop and schedule the next slice.
  • Yield between slices — defer the continuation via schedule (requestIdleCallback/setTimeout in the browser) so the browser can paint and stay responsive.
  • Never starve — always run at least one task per slice, so a single long task can't wedge the queue forever.
  • Bookkeepingadd returns a cancel; size/isRunning report state; onDrain fires once when the queue empties. Adding while running must not start a second loop.

Unlock the solution & editor

  • Runnable editor + tests

    Solve in the browser with instant Jest feedback.

  • Detailed solutions

    Walkthroughs, edge cases, and complexity notes.

  • Multi-framework variants

    React, Vue, Vanilla, Angular — same question, different stacks.

Upgrade to Premium