CodePark/ questions / Long tasks & the main thread
START PRACTICINGPRACTICE
Frontend question · Browser & web performance › Long tasks & the main thread

What is a long task, why does it make a page feel slow, and how do you break one up?

function yieldToMain() {
  if (globalThis.scheduler?.yield) return scheduler.yield();
  return new Promise((resolve) => setTimeout(resolve, 0));
}

async function processAll(items) {
  let start = performance.now();
  for (const item of items) {
    process(item);
    if (performance.now() - start > 50) {
      await yieldToMain();
      start = performance.now();
    }
  }
}

A long task is any piece of work on the main thread that takes more than 50 ms. The main thread is the one thread that runs your JavaScript, handles clicks and key presses, and paints the page. While one task runs, the browser can do nothing else.

So during a 400 ms task:

  • A click waits until the task ends before its handler runs.
  • The screen can't update, so animations freeze.
  • INP (Interaction to Next Paint: how fast the page responds to input) gets worse.

How to break it up:

  • Yield to the main thread. Split the work into chunks and pause between them, as in the code. Each pause lets the browser handle input and paint. scheduler.yield() is the best way to pause where it exists. setTimeout(resolve, 0) is the fallback.
  • Do less. Remove work that isn't needed right now, or wait until it is needed.
  • Move heavy work off the main thread into a Web Worker, like parsing a big file or sorting large data.
  • Do urgent work first. In an event handler, update the UI first, then yield, then do the analytics or saving.

You find long tasks in the DevTools Performance panel. They have a red corner. In the field, the Long Animation Frames API reports them.

  • A long task is main-thread work that takes more than 50 ms.
  • During a long task, the browser can't respond to input or paint.
  • Long tasks make INP worse.
  • Split the work into chunks and yield between them, with scheduler.yield() or setTimeout.
  • Move heavy computation into a Web Worker.
  • In event handlers, update the UI first and defer the rest.