No Login Data Private Local Save

isInputPending() API Demo - Online Yield to User

7
0
0
0

isInputPending() API Demo

Visualize how navigator.scheduling.isInputPending() helps yield the main thread to keep UIs responsive during heavy computation.

Blocking
Without isInputPending

Long task runs uninterrupted — input events are queued.

Task Progress 0%
--
Last Click Latency
0
Work Units Done
Click while task is running to measure delay Type to feel input lag
Yielding
With isInputPending

Checks for pending input & yields the main thread proactively.

Task Progress 0%
--
Last Click Latency
0
Work Units Done
Click while task is running to measure delay Type to feel input lag
Ready to run. Click the button above to start the demo.
Usage Example
// Check if the API is available if ('scheduling' in navigator && 'isInputPending' in navigator.scheduling) { // Inside your long-running task loop: for (let i = 0; i < totalWork; i += batchSize) { doWork(batchSize); // Check for pending input (discrete events like click, keydown) if (navigator.scheduling.isInputPending()) { await yieldToMain(); // setTimeout(0) or similar } // Or include continuous events (mousemove, wheel) if (navigator.scheduling.isInputPending({ includeContinuous: true })) { await yieldToMain(); } } }
Frequently Asked Questions
navigator.scheduling.isInputPending() is a web API that allows JavaScript to check whether there are pending user input events (like clicks, key presses, or touches) waiting in the browser's event queue. It returns a boolean — true if input is waiting to be processed, false otherwise. This enables long-running tasks to proactively yield the main thread only when the user actually needs to interact, rather than yielding on a fixed schedule.
As of 2025, Chromium-based browsers (Google Chrome 87+, Microsoft Edge 87+, Opera 73+, Samsung Internet 16+) support this API. Firefox and Safari do not yet implement it natively. You should always use feature detection: 'scheduling' in navigator && 'isInputPending' in navigator.scheduling. For unsupported browsers, consider falling back to periodic setTimeout(0) yielding or using a polyfill.
Discrete events (default): click, keydown, keyup, mousedown, mouseup, touchstart, touchend — these indicate intentional user actions.

Continuous events (opt-in via {includeContinuous: true}): mousemove, wheel, touchmove, pointermove — these fire frequently during movement. Including them can cause excessive yielding, so only use this option when responsiveness to continuous input (like drawing or dragging) is critical.
INP (Interaction to Next Paint) measures a page's overall responsiveness to user interactions. Long main-thread tasks are the primary cause of poor INP scores. By using isInputPending(), developers can break up long tasks and yield precisely when input is waiting, dramatically reducing interaction latency. This directly improves INP, Total Blocking Time (TBT), and the overall user experience — especially on slower devices or during heavy computation.
requestIdleCallback schedules work during browser idle periods — but it doesn't check for pending input specifically. A page can be "idle" in terms of rendering yet still have unprocessed input events. isInputPending() fills this gap by allowing synchronous, on-demand checking of the input queue, giving developers finer-grained control over when to yield. They can be used together for optimal scheduling.
  • Check at natural breakpoints — every few milliseconds of work, not after every single operation.
  • Use with async patterns — combine with setTimeout(0), postMessage, or scheduler.yield() to actually yield the thread.
  • Batch your work — process a reasonable chunk (e.g., 5-15ms) between checks.
  • Default to discrete events — only use includeContinuous: true when necessary.
  • Always feature-detect — provide fallbacks for unsupported browsers.
  • Measure impact — use the Performance API or Long Tasks API to verify improvements.
A true polyfill isn't possible because JavaScript cannot inspect the browser's native input queue. However, you can implement a fallback strategy: wrap the API call in a helper function that returns false (or uses a timer-based heuristic) when isInputPending is unavailable. Combined with periodic setTimeout(0) yielding, this provides reasonable behavior across all browsers, though without the precision of the native API.
Common use cases include: data processing dashboards with heavy filtering/sorting, code editors performing syntax analysis, spreadsheet applications recalculating formulas, game loops with AI computation, image/video processing in the browser, and any search/filter functionality over large datasets. Any scenario where the main thread does significant work while the user may want to interact benefits from this API.
No — isInputPending() is designed to be extremely fast (sub-microsecond). It simply checks a flag maintained by the browser's event loop, without traversing the event queue or performing any heavy work. You can safely call it thousands of times per second. The real performance consideration is how often you yield — yielding too frequently can slow down the overall task, while yielding too rarely reduces responsiveness. Finding the right batch size is key.
scheduler.yield() is a newer proposal (part of the Prioritized Task Scheduling API) that actively yields the main thread and returns a promise. While isInputPending() is a read-only check, scheduler.yield() is an action. They complement each other: you can use isInputPending() to decide whether to yield, and scheduler.yield() (or setTimeout(0)) to actually perform the yield. This combination gives developers the most control over main-thread scheduling.