Cómo ceder al hilo principal

Cede al hilo principal para mejorar la capacidad de respuesta de la página

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-02-07

Ceder al hilo principal

Imagina una película romántica. El escenario es un pequeño mercado francés en el centro de un pequeño pueblo. Las calles están llenas de parejas bebiendo café, comiendo croissants y comprando flores. Ahora imagina qué sucede cuando solo 1 vendedor puede vender algo a un comprador simultáneamente mientras todos los demás tienen que esperar su turno. El panadero se inunda de pedidos, estallan discusiones en la floristería y el paseo romántico se convierte en una espera frustrante.

Bueno...  eso es más o menos lo que sucede en un sitio web cuando las cosas se ponen demasiado ocupadas.

La importancia de ceder

El hilo principal de un navegador maneja todos los procesos importantes y programa todas las tareas importantes (analizar HTML y CSS, ejecutar código JavaScript, manejar eventos de entrada como clics y desplazamientos, y renderizado visual). 

El hilo principal de un navegador se ejecuta en un modelo de un solo hilo. Esto significa que solo puede realizar una tarea a la vez. Cuando una tarea (generalmente ejecución de JavaScript o renderizado) comienza a ejecutarse, el navegador ejecutará esta tarea 'hasta su finalización' y no se detendrá hasta que termine. Esto significa que no programará ni realizará ninguna otra tarea hasta que la tarea anterior esté lista. Esto se llama 'bloquear el hilo principal'. Bloquear el hilo principal es un problema cuando los visitantes interactúan con una página porque la página no responderá durante el tiempo de bloqueo. 

Una forma de solucionar el bloqueo del hilo principal es 'Cediendo al hilo principal'. Ceder es una técnica donde las tareas largas se dividen en múltiples tareas más pequeñas  para permitir que el hilo principal maneje tareas más importantes (como la entrada del usuario). 

Tareas largas y periodo de bloqueo: Cuando una tarea toma más de 50 milisegundos, se clasifica como una tarea larga, y cualquier cosa más allá de ese umbral de 50 milisegundos se conoce como el 'periodo de bloqueo' de la tarea. Dividir estas tareas largas en fragmentos más pequeños permite que el navegador permanezca receptivo, incluso cuando maneja operaciones computacionalmente intensivas.

Viejas estrategias de cesión

Antes de la nueva Prioritized Task Scheduling API había 4 formas de ceder al hilo principal. ¡Todas tienen sus limitaciones y preocupaciones!

  • setTimeout(): La estrategia más común, setTimeout() funciona ejecutando código en una función callback después de un retraso especificado. Al establecer un retraso (o timeout) de 0. setTimeout() añade la tarea al final de la cola, permitiendo que otras tareas se ejecuten primero. Un problema importante es que, setTimeout() no está diseñado para una programación precisa porque las tareas solo pueden empujarse al final de la cola.
  • requestAnimationFrame(): requestAnimationFrame() funciona poniendo en cola una función para ser ejecutada antes del siguiente repintado del navegador. requestAnimationFrame() a menudo se combina con setTimeout() para asegurar que las funciones callback se programen después de la siguiente actualización de diseño.
  • requestIdleCallback(): Este método es el más adecuado para tareas no críticas y de baja prioridad que pueden ser ejecutadas durante el tiempo de inactividad de un navegador. Aunque ayuda a mantener el hilo principal libre para tareas más cruciales, requestIdleCallback() sufre de una limitación significativa: no hay garantía de que las tareas programadas se ejecuten pronto (¡¡o nunca!!), especialmente en un hilo principal ocupado.
  • isInputPending(): isInputPending() funciona comprobando entradas de usuario pendientes y cediendo solo si se detecta una entrada. isInputPending() se puede usar para trabajar junto con otras funciones de cesión para evitar cesiones innecesarias. Desafortunadamente, puede devolver falsos negativos y no aborda la necesidad de ceder para otras tareas críticas para el rendimiento como las animaciones.

Presentando: scheduler.yield()

Las limitaciones de estos 4 métodos han sido una preocupación para el equipo de Chrome, especialmente con muchos sitios fallando en la métrica Interaction to Next Paint. Para solucionar esto y ayudar, el equipo de Chrome ha construido una nueva API que da control granular sobre la programación de javascript.

¡Conoce a scheduler.yield()! Con window.scheduler.yield() los desarrolladores pueden ceder efectivamente al hilo principal inmediatamente sin reorganizar el orden de las tareas o crear complejidad extra.

Usa Scheduler.yield() efectivamente

¡Sumerjámonos en el código y exploremos cómo aprovechar scheduler.yield() de la manera en que está destinado a ser! Antes de comenzar a usar scheduler.yield(), es importante verificar la compatibilidad del navegador porque es una característica experimental y no todos los navegadores la soportan todavía. 

Código de ejemplo

function yieldToMain() {
  if ('scheduler' in window && 'yield' in window.scheduler) {
    return window.scheduler.yield();
  }
  return new Promise((resolve) => {
    setTimeout(resolve, 0);
  });
}

La función yieldToMain() es el núcleo de ceder el control al hilo principal. Primero verifica que tanto window.scheduler como window.scheduler.yield existan. Si lo hacen, podemos usar window.scheduler.yield de forma segura. Si  window.scheduler.yield no está soportado el código recurre a setTimout).

Versión más corta y lista para producción

O usa esta versión más corta y lista para producción que usa el operador ternario:

/* o más corto y listo para producción: */
function yieldToMain(){
  return"scheduler"in window&&"yield"in window.scheduler?
  window.scheduler.yield():new Promise(e=>{setTimeout(e,0)})
}

Ejemplo de la vida real: Mejorando la búsqueda con yieldToMain():

Veamos cómo podemos usar yieldToMain() para mejorar la experiencia de búsqueda para tus usuarios:

La función handleSearch() demuestra cómo yieldToMain() puede usarse efectivamente. Primero actualiza el contenido del botón para proporcionar retroalimentación inmediata de que una búsqueda está en progreso. Puedes usar yieldToMain() aquí para permitir que el navegador actualice el diseño.

A continuación, fetchData() recupera datos de búsqueda, y updateHTML(data) muestra los resultados. Otro  yieldToMain() asegura una actualización rápida del diseño (ya que nunca podemos estar seguros de que no haya otros oyentes de eventos esperando después de esta tarea).  Finalmente otras tareas menos importantes se programan durante el tiempo de inactividad del navegador. Ten en cuenta que no cedí al hilo principal aquí ya que requestIdleCallback() solo se ejecutará cuando el hilo principal esté inactivo.

async function handleSeach(){
 /* actualizar rápidamente el contenido del botón después de enviar*/
 updateButtontoPending();

 /* Ceder al Main */
 await yieldToMain();

 /* obtener datos y actualizar html*/
 const data = await fetchData();
 updateHTML(data);

 /* Ceder al Main de nuevo */
 await yieldToMain();

 /* alguna función solo debería ejecutarse durante el tiempo de inactividad del navegador*/
 requestIdleCallback(sendDataToAnalytics);
}

Por qué scheduler.yield() es simplemente mejor

A diferencia de setTimeout(), que añade tareas diferidas al final de la cola de tareas, scheduler.yield() solo pausa la cola de javascript y las tareas pausadas permanecen al frente de la cola, asegurando que se ejecuten tan pronto como sea posible después de que se hayan completado tareas de mayor prioridad (como manejar callbacks de entrada). Este comportamiento de "frente de cola" aborda el mayor problema de los viejos métodos de cesión. Y los desarrolladores ahora pueden 'ceder al hilo principal' sin el riesgo de que sus tareas importantes se retrasen por otras tareas menos importantes.

Otra ventaja de scheduler.yield() es que está diseñado para funcionar con la Prioritized Task Scheduling API como scheduler.postTask(), que permite priorizar tareas basándose en su importancia. Esta combinación de características proporciona a los desarrolladores un potente conjunto de herramientas para optimizar sus aplicaciones web para capacidad de respuesta y rendimiento.


Cómo ceder al hilo principalCore Web Vitals Cómo ceder al hilo principal