You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
requestIdleCallback wrapper for scheduling low-priority work during browser idle
time.
Quick Start
import{IdleCallback}from'@zappzarapp/browser-utils/idle';// Schedule work when browser is idleconstcancel=IdleCallback.request((deadline)=>{while(deadline.timeRemaining()>0&&hasMoreWork()){doWorkChunk();}});// Run multiple tasks in idle timeconstcleanup=IdleCallback.runTasks([()=>prefetchImages(),()=>updateAnalytics(),()=>cleanupCache(),]);
API Reference
Core API
Method
Returns
Description
isSupported()
boolean
Check if requestIdleCallback is supported
request(callback, options?)
CleanupFn
Request idle callback
requestPromise(options?)
Promise<IdleDeadline>
Request as Promise
runIfTime(deadline, task, minTime?)
boolean
Run task if enough time remaining
Task Queue
Method
Returns
Description
runTasks(tasks, options?)
CleanupFn
Run tasks across idle periods
processInIdle(items, processor, options?)
Promise<void>
Process array items in idle time
Utilities
Method
Returns
Description
defer(fn, options?)
(...args) => CleanupFn
Create idle-deferred function
batch(fn, options?)
{ schedule, flush, cancel }
Create batched idle function
Types
interfaceIdleDeadline{readonlytimeRemaining: ()=>number;// Time remaining in msreadonlydidTimeout: boolean;// Whether timeout expired}interfaceIdleOptions{readonlytimeout?: number;// Max wait time before forcing execution}interfaceTaskQueueOptionsextendsIdleOptions{readonlyminTimeRemaining?: number;// Min time to start task (default: 1ms)}
Usage Examples
Deadline-Aware Work
IdleCallback.request((deadline)=>{// Process items while we have timewhile(deadline.timeRemaining()>1&&items.length>0){constitem=items.shift()!;processItem(item);}// If more items remain, schedule another callbackif(items.length>0){IdleCallback.request(processMoreItems);}});
Background Data Processing
// Process large dataset without blocking UIasyncfunctionprocessDataset(data: DataItem[]): Promise<void>{awaitIdleCallback.processInIdle(data,(item,index)=>{// Process each itemtransformData(item);updateProgress(index/data.length);},{timeout: 5000}// Force completion within 5 seconds);console.log('Processing complete');}
Prefetching Resources
// Prefetch resources during idle timeconstcleanup=IdleCallback.runTasks([()=>prefetchRoute('/dashboard'),()=>prefetchRoute('/settings'),()=>prefetchImages(['hero.jpg','profile.jpg']),()=>warmCache(),]);// Cancel if user navigates awaywindow.addEventListener('beforeunload',cleanup);
Deferred Analytics
// Defer non-critical analyticsconsttrackEvent=IdleCallback.defer((eventName: string,data: object)=>{analytics.track(eventName,data);},{timeout: 10000}// Send within 10 seconds);// Use anywherebutton.addEventListener('click',()=>{// Critical work firsthandleButtonClick();// Analytics can wait for idle timetrackEvent('button_clicked',{buttonId: 'submit'});});
Batched Updates
// Batch DOM updates to run during idle timeconstbatchedUpdate=IdleCallback.batch(()=>{// Expensive DOM operationrecalculateLayout();updateAllElements();});// Multiple calls are batched into onewindow.addEventListener('resize',()=>{batchedUpdate.schedule();// Won't run immediately});// Force immediate execution if neededfunctionforceUpdate(): void{batchedUpdate.flush();}// Cancel pending updatefunctioncancelUpdate(): void{batchedUpdate.cancel();}
Lazy Initialization
// Initialize non-critical features during idle timedocument.addEventListener('DOMContentLoaded',()=>{// Critical path firstinitCriticalFeatures();// Non-critical can waitIdleCallback.runTasks([()=>initAnalytics(),()=>initChatWidget(),()=>initTooltips(),()=>setupKeyboardShortcuts(),()=>preloadFonts(),]);});
Timeout Handling
// Ensure work completes within time limitIdleCallback.request((deadline)=>{if(deadline.didTimeout){// Browser forced execution due to timeout// Do minimal necessary workdoMinimalWork();}else{// Normal idle time - do full workdoFullWork(deadline);}},{timeout: 2000}// Force after 2 seconds);
Promise-Based Usage
asyncfunctiondoIdleWork(): Promise<void>{// Wait for idle timeconstdeadline=awaitIdleCallback.requestPromise();console.log(`Got ${deadline.timeRemaining()}ms of idle time`);// Do workperformBackgroundTask();}
Conditional Execution
IdleCallback.request((deadline)=>{// Only run expensive operation if we have enough timeif(IdleCallback.runIfTime(deadline,expensiveOperation,10)){console.log('Operation completed');}else{// Not enough time, schedule for laterIdleCallback.request(retryOperation);}});
Fallback Behavior
When requestIdleCallback is not supported (Safari < 16.4, older browsers):
Falls back to setTimeout with 1ms delay
Provides a synthetic deadline with 50ms time budget
didTimeout is set based on timeout option
// Works the same in all browsersif(!IdleCallback.isSupported()){console.log('Using setTimeout fallback');}// API is identical regardless of supportIdleCallback.request((deadline)=>{// deadline.timeRemaining() works in both casesdoWork();});
Performance Considerations
Don't Block - Keep individual work chunks small (< 50ms)
Use Timeout - Set timeout for time-sensitive work
Check Time Remaining - Always check deadline.timeRemaining() before
expensive operations
Batch Related Work - Group related tasks to minimize callback overhead
Prioritize - Order tasks by importance in runTasks
Cancel Unused - Call cleanup function when tasks are no longer needed
Best Practices
Critical Path First - Never put critical work in idle callbacks
Progressive Enhancement - App should work even if idle work is delayed
User Experience - Idle callbacks should improve, not degrade, user
experience
Testing - Test with and without idle callback support
Monitoring - Track if timeout is frequently triggered (indicates too much
work)