Prioritized Task Scheduling

scheduler.postTask(fn, { priority, signal }) queues work as 'user-blocking', 'user-visible' (default) or 'background'; a TaskController can abort it or change its priority. await scheduler.yield() lets input and rendering run mid-job, then resumes ahead of same-priority tasks, whereas setTimeout() resumes at the back of the queue. Both are Limited availability: postTask() since Chrome 94 1 , yield() since Chrome 129, both in Firefox 142 555 (August 2025), not in Safari 10 .

Task priorities and a chunked job that yieldsJavaScript
scheduler.postTask(() => console.log('background task'), { priority: 'background' });
scheduler.postTask(() => console.log('user-visible task'));
scheduler.postTask(() => console.log('user-blocking task'), { priority: 'user-blocking' });
const yieldToMain = () => globalThis.scheduler?.yield?.() ??
  new Promise((resolve) => setTimeout(resolve));          // fallback for Safari
for (let chunk = 0, sum = 0; chunk < 20; chunk++) {
  for (let i = 0; i < 3e6; i++) sum += i % 2;              // a few ms of work
  await yieldToMain();                                     // input can run here
}
console.log('20 chunks done');
Output
user-blocking task
20 chunks done
user-visible task
background task

The yielding loop still beat the queued user-visible task. Yield at least every 50 ms to keep Interaction to Next Paint low.