Come fare Yield al Main Thread per migliorare INP
Usa scheduler.yield() per suddividere le long task e mantenere le tue pagine reattive

Yield to the main thread
Immagina un film romantico. L'ambientazione è un piccolo mercato francese nel centro di un piccolo villaggio. Le strade sono piene di coppie che bevono caffè, mangiano croissant e comprano fiori. Ora immagina cosa succede quando solo un acquirente alla volta può comprare qualcosa da un venditore, mentre tutti gli altri devono aspettare il loro turno. Il panettiere viene sommerso di richieste, scoppiano litigi dal fioraio e la passeggiata romantica si trasforma in un'attesa frustrante.
Beh... è più o meno quello che succede su un sito web quando le cose diventano troppo impegnative.
Ultima revisione di Arjen Karel a marzo 2026
Perché il yielding è importante per INP
Il main thread di un browser gestisce tutti i processi importanti: parsing di HTML e CSS, esecuzione di JavaScript, gestione degli eventi di input come clic e scroll, e rendering visivo. Funziona su un modello single-threaded, il che significa che può eseguire solo un'attività alla volta. Quando un'attività inizia, il browser la eseguirà fino al completamento e non si fermerà finché non è terminata. Nessun'altra attività viene pianificata finché quella corrente non è completata. Questo si chiama bloccare il main thread.
Bloccare il main thread è la causa principale di punteggi Interaction to Next Paint (INP) scarsi. Quando un visitatore clicca un pulsante e il tuo JavaScript blocca il main thread per 200ms, il browser non può renderizzare una risposta finché lo script non termina. La fase di processing time di INP misura esattamente questo ritardo. Secondo la 2025 Web Almanac, il Total Blocking Time mediano su mobile è di 1.916ms, in aumento del 58% rispetto all'anno precedente. Si tratta di quasi 2 secondi durante i quali il browser non può rispondere all'input dell'utente.
Un modo per risolvere questo problema è fare yield al main thread. Il yielding è una tecnica in cui le attività lunghe vengono suddivise in più attività più piccole per consentire al browser di gestire lavori più importanti (come rispondere all'input dell'utente) tra di esse.
Long task e periodo di blocco: Quando un'attività impiega più di 50 millisecondi, viene classificata come long task, e tutto ciò che supera la soglia dei 50 millisecondi è noto come il "periodo di blocco" dell'attività. Suddividere queste long task in blocchi più piccoli consente al browser di rimanere reattivo, anche durante operazioni computazionalmente intensive.
Vecchie strategie di yielding
Prima della Prioritized Task Scheduling API c'erano 4 modi per fare yield al main thread. Tutti hanno limitazioni.
- setTimeout(): La strategia più comune.
setTimeout()con un ritardo di 0 aggiunge l'attività alla fine della coda, consentendo ad altre attività di essere eseguite prima. Il problema: le attività possono essere spostate solo alla fine della coda, quindi altri script possono passare avanti prima che il tuo codice riprenda. Le chiamate annidate disetTimeout()impongono anche un ritardo minimo di 5ms dopo cinque cicli. - requestAnimationFrame(): Accoda una funzione da eseguire prima del prossimo repaint del browser. Spesso combinato con
setTimeout()per garantire che i callback vengano pianificati dopo il prossimo aggiornamento del layout. Non progettato per il yielding; progettato per il lavoro di animazione. - requestIdleCallback(): Più adatto per attività non critiche e a bassa priorità che possono essere eseguite durante i tempi di inattività del browser. La limitazione: non c'è garanzia che le attività pianificate vengano eseguite tempestivamente (o del tutto) su un main thread occupato.
- isInputPending(): Controlla gli input dell'utente in sospeso e fa yield solo se viene rilevato un input. Google non raccomanda più questo approccio. Può restituire falsi negativi e non tiene conto di altri lavori critici per le prestazioni come animazioni e aggiornamenti di rendering.
scheduler.yield()
Le limitazioni di questi metodi sono state una preoccupazione per il team Chrome, soprattutto con molti siti che non superano INP. Per risolvere questo problema, hanno creato scheduler.yield(): una nuova API che consente agli sviluppatori di fare yield al main thread immediatamente senza riordinare le attività o aggiungere complessità.
scheduler.yield() è disponibile in versione stabile in Chrome 129 (settembre 2024) ed è ora supportato da tutti i principali browser tranne Safari.
Esempio di codice
Poiché Safari non supporta ancora scheduler.yield(), usa un fallback a setTimeout():
function yieldToMain() {
if ('scheduler' in window && 'yield' in window.scheduler) {
return window.scheduler.yield();
}
return new Promise((resolve) => {
setTimeout(resolve, 0);
});
}
La funzione yieldToMain() verifica se window.scheduler.yield esiste. Se sì, utilizza l'API nativa. In caso contrario, il codice ricorre a setTimeout(). Questo corrisponde al pattern raccomandato da Google.
Per i progetti che necessitano della Prioritized Task Scheduling API completa (inclusi scheduler.postTask() e TaskController), Google Chrome Labs mantiene un polyfill ufficiale.
Esempio reale: migliorare la ricerca con yieldToMain()
Ecco come yieldToMain() può migliorare l'esperienza di ricerca per i tuoi utenti.
La funzione handleSearch() prima aggiorna il contenuto del pulsante per dare un feedback immediato che una ricerca è in corso, poi fa yield per consentire al browser di renderizzare quell'aggiornamento. Successivamente, fetchData() recupera i dati di ricerca e updateHTML(data) visualizza i risultati. Un altro yieldToMain() assicura un rapido aggiornamento del layout. Infine, le attività meno importanti vengono pianificate durante il tempo di inattività del browser. Nota che non ho fatto yield prima di requestIdleCallback() poiché viene eseguito solo quando il main thread è inattivo comunque.
async function handleSearch() {
/* quickly update the button content after submitting */
updateButtonToPending();
/* Yield to Main */
await yieldToMain();
/* fetch data and update html */
const data = await fetchData();
updateHTML(data);
/* Yield to Main again */
await yieldToMain();
/* some functions should only run during browser idle time */
requestIdleCallback(sendDataToAnalytics);
}
Per un altro esempio pratico, scopri come utilizzare lo stesso pattern di yield con i push di dataLayer per impedire che gli script di analytics blocchino le interazioni.
Perché scheduler.yield() è migliore
A differenza di setTimeout(), che aggiunge le attività differite alla fine della coda delle attività, scheduler.yield() mette in pausa l'esecuzione e posiziona la continuazione all'inizio della coda. Il tuo codice riprende non appena il lavoro a priorità più alta (come la gestione dei callback degli input) è completato. Questa è la differenza chiave: puoi fare yield al main thread senza il rischio che altri script passino avanti prima che il tuo codice riprenda.

scheduler.yield() è anche progettato per funzionare con la Prioritized Task Scheduling API. Quando chiamato all'interno di un callback di scheduler.postTask(), scheduler.yield() eredita il livello di priorità dell'attività. Questa combinazione ti offre un controllo granulare su come il tuo JavaScript viene prioritizzato e quando fa yield.
Supporto browser
scheduler.yield() è supportato dal 71,5% dei browser a livello globale:
- Chrome 129+ e Edge 129+: stabile da settembre 2024
- Firefox 142+: stabile da agosto 2025
- Safari: non supportato, nessuna tempistica annunciata
Il fallback a setTimeout() nella funzione yieldToMain() sopra garantisce che il tuo codice funzioni in tutti i browser. Gli utenti Safari ottengono il comportamento precedente in cui le continuazioni vanno in fondo alla coda, ma la pagina fa comunque yield. Man mano che il supporto browser cresce, più utenti otterranno automaticamente la ripresa più veloce.
Se il problema sono gli script di terze parti che bloccano completamente il main thread, differire quegli script è un primo passo migliore rispetto al yielding. Il yielding aiuta quando il tuo stesso codice deve svolgere molto lavoro ma vuoi che il browser rimanga reattivo tra i blocchi.
Per verificare che il yielding stia migliorando il tuo INP sul campo, monitora le tue pagine con Real User Monitoring. Gli strumenti di laboratorio come Lighthouse misurano il Total Blocking Time, ma solo i dati sul campo ti mostrano l'effettivo INP che i tuoi visitatori sperimentano.
Pinpoint the route, device, and connection that fails.
CoreDash segments every metric by route, device class, browser, and connection type. Real time data. Not the 28 day average Google gives you.
Explore Segmentation
