Los cálculos pesados o los bucles largos pueden bloquear el subproceso principal, lo que hace que la página deje de responder. Para evitarlo, debes devolver el control al navegador de forma periódica. La API de scheduler.yield() te permite pausar una tarea larga y dejar que el navegador controle la entrada del usuario o la renderización antes de continuar.
Cómo dividir las tareas largas
Usa scheduler.yield() dentro de las funciones asíncronas para dividir el trabajo.
async function processLargeArray(items) {
// DO: Set a time-based deadline 50 milliseconds into the future. 50
// milliseconds is the boundary for when a task becomes a long task.
let deadline = performance.now() + 50; // 50ms budget
for (const item of items) {
// Process the item
processItem(item);
// MANDATORY: Yield to the main thread periodically to keep the UI
// responsive. This can be done by checking if the deadline set earlier
// has been exceeded. When it has been, yield, then reset the deadline
// another 50 milliseconds into the future.
if (performance.now() >= deadline) {
await scheduler.yield();
deadline = performance.now() + 50;
}
}
}
Estrategias de resguardo
Es posible que algunos navegadores no admitan la API de scheduler. DEBES implementar un resguardo con setTimeout para garantizar que la ejecución de código se ejecute sin errores.
Resguardo para scheduler.yield()
async function processLargeArrayWithFallback(items) {
// DO: Set a time-based deadline 50 milliseconds into the future.
let deadline = performance.now() + 50;
for (const item of items) {
processItem(item);
// MANDATORY: Yield to the main thread periodically to keep the UI responsive.
if (performance.now() >= deadline) {
// DO: Feature detect scheduler.yield
if ('scheduler' in window && 'yield' in window.scheduler) {
await scheduler.yield();
} else {
// DO: Fallback to setTimeout for older browsers
await new Promise(resolve => setTimeout(resolve, 0));
}
deadline = performance.now() + 50;
}
}
}