A introdución. Ás veces, só unha función de JavaScript de longa duración é suficiente para conxelar a interface, deixando aos usuarios frustrados e inseguros se a aplicación aínda está a funcionar ou conxelou. Introduce un método pequeno pero poderoso: Permite a un usuario pausar a execución, dando ao navegador a oportunidade de manexar tarefas máis importantes (como clics ou escribir), e despois continuar onde deixaron. , explorar vellos workarounds, e ver como Facer a vida máis fácil. Planificación de tarefas API Páxina oficial.yield() Main Thread scheduler.yield() ¿Que é o calendario.yield()? Entón, o que é É un método do Interface do novo Este método permítelle, como desenvolvedor, pausar a súa execución de JavaScript e render explicitamente o control de volta ao - para que poida manexar outras tarefas importantes pendentes, como interaccións de usuario, clics, escritos, etc., e despois continuar a execución desde onde deixou. Vostede está dicindo ao navegador: scheduler.yield() Calendario Programación de tarefas prioritarias API. Main Thread scheduler.yield() "Agora, tome unha respiración, imos parar a tarefa actual e centrarse noutras tarefas non menos ou máis importantes. "Agora, tome unha respiración, imos parar a tarefa actual e centrarse noutras tarefas non menos ou máis importantes. Isto fai que a súa páxina sexa máis responsiva, especialmente cando executa tarefas JavaScript longas ou pesadas. - que é todo sobre a rapidez coa que o navegador responde á entrada do usuario. Interacción coa seguinte pintura (INP) A terminoloxía. Antes de mergullarse máis profundamente, imos pasar rapidamente por algúns termos básicos que se usarán ao longo do artigo. Main Thread - Este é o lugar central onde o navegador fai a maior parte do seu traballo. Xestiona a renderización, o deseño e executa a maior parte do código JavaScript. Tarefa longa - Esta é calquera tarefa de JavaScript que mantén o tema principal ocupado por moito tempo, xeralmente máis de 50 milisegundos. Tarefa de bloqueo: É unha operación sincronizada no tema principal que impide ao navegador procesar outras cousas importantes, como responder a clics ou actualizar a interface. O problema . para coñecer a beleza do , primeiro ten que comprender o problema que está intentando resolver. JavaScript funciona nun único fío. Isto significa que só pode facer unha cousa á vez. Se o seu código mantén o fío ocupado, todo o demais - renderización, clics de botóns, escritura de entrada ten que esperar. Nun mundo ideal, sempre dividiría tarefas pesadas en pequenas pezas. Pero a realidade é confusa. Trátase de código herdado, scripts de terceiros ou cálculos pesados inevitables. E cando iso ocorre, os usuarios atópanse con páxinas conxeladas. scheduler.yield() Modelo de execución de JavaScript. Como un refresco rápido, aquí está un diagrama de exemplo de como procesan as tarefas JavaScript - noutras palabras, como o Estou seguro de que moitos de vostedes viron diagramas como este antes - as filas de tarefas, o ciclo de eventos, a pila de chamadas. JavaScript Execution Model Imos percorrer as principais ideas paso a paso: Todo o código sincronizado vai directamente ao Call Stack e é executado liña por liña, función por función. Segue o principio LIFO - último en, primeiro fóra. JavaScript é executado nun único thread, o que significa que só pode facer unha cousa á vez. As operacións asíncronas (como setTimeout, fetch) son manexadas fóra do Thread Principal - polas APIs da Web (proporcionadas polo navegador ou o ambiente). Unha vez feitas, non volven directamente ao Stack de chamadas. En lugar diso, as súas chamadas son en cola - ou na cola de microtasks (por exemplo, Promise.then, cola de Microtasks) ou na cola de macrotasks (por exemplo, setTimeout, setInterval). Cando o Stack de chamadas está baleiro, o Loop de eventos comproba a cola de microtascas e executa todas as microtascas unha por unha en orde. Só despois diso, toma unha macrotask da cola e execútala. Se, durante o proceso, se engaden novas microtascas, execútanse antes da seguinte macrotasca. Este ciclo continúa: todas as microtascas → unha macrotasca → repetir. O novo código sincronizado entra na pila de chamadas cando chegan novas tarefas, como un usuario facendo clic nun botón, executando un novo script ou cando unha microtarefa ou macrotarefa executa a súa chamada. Esta é unha explicación moi breve e superficial, só para lembrar como funciona. Descrición do problema. Agora que refrescaron a súa comprensión de como JavaScript executa tarefas, botemos unha ollada máis de cerca ao problema real que vén con este modelo. O problema é simple: cando unha tarefa leva demasiado tempo no fío principal, bloquea todo o demais - interaccións de usuario, renderización de actualizacións e animacións. Isto leva ao conxelamento de UI e baixa resposta. O primeiro pensamento obvio pode ser: "Ben, só non escriba funcións longas ou pesadas, e iso é. O problema está resolto!". E si, iso é certo - nun mundo ideal, sempre dividiría o código pesado en partes máis pequenas, optimizaría todo e evitaría bloquear o fío principal. Pero sexamos honestos - moitos de nós entraron nestes problemas, aínda que non fomos os que os causaron orixinalmente. Mesmo se non fuches o " Para iso, crearemos unha función chamada que actúa como unha tarefa de bloqueo para o filo principal durante o período de tempo especificado.A función simula este tipo de cálculo "pesado" en cada elemento da matriz. blockingTask() Nas miñas explicacións, ás veces refírome a liñas específicas (por exemplo, "line 5 fai X"). Nas miñas explicacións, ás veces refírome a liñas específicas (por exemplo, "line 5 fai X"). function blockingTask(ms = 10) { const arr = []; const start = performance.now(); while (performance.now() - start < ms) { // Perform pointless computation to block the CPU. arr.unshift(Math.sqrt(Math.random())); } return arr; } Non hai nada fantástico sobre a función, aquí está todo o que fai: Acepta un argumento - o número de milisegundos. Este é o tempo mínimo que a función executará, ocupando así o fío principal. Crea unha matriz baleira. Crea unha hora de inicio (como hora actual). Despois corre un tempo loop ata que o tempo especificado pasou. Dentro do loop, só fai cálculos aleatorios e sen sentido para simular a carga. Finalmente, devolve o resultado dos cálculos. A función non fai nada útil, pero simula un escenario do mundo real de carga pesada. Imaxina unha situación común onde ten que loop a través dunha serie de datos e aplicar ese traballo pesado a cada elemento. Para iso, crearemos unha Funcións : heavyWork() function heavyWork () { const data = Array.from({ length: 200 }, (_, i) => i) const result = [] for (let i = 0; i < data.length; i++) { result.push(blockingTask(10)) } return result; } En que ocorre o seguinte: Na liña 2, crea unha matriz de 200 elementos, só números de 0 a 199. Quero notar que 200 elementos non son tantos, pero será suficiente para ver a esencia do problema. A continuación, créase unha nova matriz de "resultados" baleira para almacenar os valores procesados. A liña 5 declara un ciclo que percorre toda a lonxitude da matriz de datos. Dentro do loop, executamos a función de bloqueoTask() simulando 10 milisegundos de traballo para cada elemento, e o resultado engádese á matriz "resultado". Unha vez máis, quero lembrarlle que, para a demostración, a función de bloqueoTask() non leva ningunha carga semántica. Simplemente realiza algún traballo imaxinario, intensivo en recursos. No mundo real, podería ser algún procesamento intensivo de traballo dun elemento de matriz. Finalmente, devolve a matriz resultante. Só 10 milisegundos por elemento, e só 200 elementos - pero xuntos, bloquean o fío principal por 2 segundos completos. A demostración do problema. Agora é hora de mirar o problema non só en teoría, senón en acción.Esta non é unha demostración completa aínda - pensalo como un visual simplificado para axudar a ver claramente o problema. Aquí está o que ves: A ventá esquerda, titulada "Configuración", permítelle activar e desactivar o bloqueo de fío principal - o que significa que a función de bloqueoTask() está realmente en execución. Tamén pode cambiar a funcionalidade scheduler.yield() - imos chegar a esa parte máis tarde. A xanela titulada "Tarefa pesada" executa a función heavyWork(). Esta é a que procesa unha matriz usando blockingTask() en cada elemento se o bloqueo de thread principal está habilitado. E a xanela titulada "Logger" só rexistra o tempo actual para a consola, incluíndo milisegundos. A ver que pasa cando o O bloqueo está desactivado, polo que as tarefas son moi lixeiras. é só un loop sobre unha matriz de 200 elementos, sen cálculos complexos. Main Thread O que observas: O usuario fai clic no botón "OK" - a función heavyWork() é executada, e inmediatamente retorna. Isto é indicado pola mensaxe HEAVY_TASK_DONE na consola, seguida do resultado - unha matriz de números. A continuación, o usuario fai clic no botón "Log" tres veces, para rexistrar a hora actual na consola - os timestamps aparecen inmediatamente, cunha lixeira diferenza de tempo. O usuario executa a función heavyWork() de novo, e de novo, resposta instantánea. Finalmente, o usuario pecha dúas fiestras, o que realmente só elimina eses elementos do DOM. Neste caso, todo se sente rápido e responsivo. O navegador non ten problemas para manexar as interaccións, porque o fío principal permanece libre. Agora imos permitir que o bloqueo, de xeito que para cada elemento da matriz, o A función será chamada cun atraso de só 10 milisegundos. Main Thread blockingTask() E agora podes observar que a interacción do usuario con elementos de interface de usuario se fixo menos suave, apareceron conxelacións de interface de usuario. O usuario preme o botón "OK", iniciando así a función heavyWork() e o primeiro atraso que ocorre é que o botón "OK" permanece visualmente presionado. Por que? Porque o navegador non pode repaint mentres heavyWork() aínda está bloqueando o fío principal. Durante este tempo, o usuario fai clic no botón "Log" catro veces - nada ocorre. Os clics son rexistrados e os seus manipuladores engadidos á cola, pero o navegador non pode reaccionar. Só despois de que heavyWork() remata vexa a saída da consola: primeiro o resultado heavyWork(), entón os catro timestamps - todos impresos nun lote. A continuación, o usuario fai clic no botón "OK" de novo. O mesmo comportamento - botón de pegada. Entón, mentres a tarefa heavyWork() está en execución, intenta pechar unha xanela facendo clic no ícono "X" tres veces. E por último, outro intento de executar heavyWork() e pechar a última fiestra. Esta demostración sinxela mostra canto tempo as tarefas bloquean a capacidade do navegador de responder ás accións do usuario. Aínda que cada chamada de bloqueo leva só 10 milisegundos, a cadeaxe de 200 deles xuntos resulta nun conxelamento de 2 segundos. O usuario non pode interactuar cos botóns, a interface non se repintou. Os eventos están en cola, pero non se procesan ata que a pila de chamadas estea clara. Isto non é só un problema de rendemento - é un problema de experiencia do usuario. E ese é exactamente o tipo de problema que queremos resolver - idealmente, sen ter que dividir manualmente a nosa lóxica en decenas de chamadas de volta. A solución do problema. Agora que entendes o problema, falemos de posibles solucións. Por suposto, a mellor estratexia é evitar tarefas longas en primeiro lugar mantendo o código eficiente e rompendo as cousas cedo. Pero, como viches, as cousas ocorren. Se é código herdado, cálculos inevitables ou só non hai tempo suficiente para optimizar, ás veces, tes que tratar con iso. Apareceu, varias solucións e trucos foron creados para mellorar a capacidade de resposta. Pero a idea central detrás de todos eles - e detrás Tamén - é moi sinxelo: Prioritized Task Scheduling API scheduler.yield() Dividir unha tarefa en anacos máis pequenos ou chamados anacos. E de cando en vez, pausa para deixar que o navegador tome o seu alento. Noutras palabras, dáslle ao tema principal a oportunidade de executar tarefas máis urxentes, como interaccións de usuario ou renderización de actualizacións, e logo volves para rematar o teu propio traballo. Aquí está o concepto de As seguintes páxinas ligan con Pseudocode: heavyWork() function heavyWork() { // Do heavy work... /** * Take a breather! * Yield the execution to the Main Thread... * */ // Continue to do heavy work... } O que está a pasar aquí: Executa unha parte da túa tarefa. A continuación, faise unha pausa, permitindo que o navegador xestione outras tarefas de alta prioridade (como actualizacións de UI). Continúa executando a función desde onde deixou. Vellos enfoques de resolución de problemas. Antes o truco máis común para xestionar tarefas de bloqueo longas era usar Ao chamalo cun atraso de 0 (zero), engade a súa tarefa de chamadas de volta ao final do en liña, permitindo que outras tarefas se executen primeiro. noutras palabras, di ao navegador: scheduler.yield() setTimeout() macrotasks "Executa esta peza de código máis tarde, despois de manexar todo o demais". "Executa esta peza de código máis tarde, despois de manexar todo o demais". É así como podes dar ao fío principal unha brecha curta entre os anacos de traballo pesado. A función podería parecer empregar este enfoque: heavyWork() async function heavyWork() { // Yield to Main Thread to avoid UI blocking before heavy work await new Promise(resolve => setTimeout(resolve, 0)) const data = Array.from({ length: 200 }, (_, i) => i) const result = [] // Interval at which execution will be yielded to the main thread (approx. ~ 25%). const yieldInterval = Math.ceil(data.length / 4) for (let i = 0; i < data.length; i++) { // Yield control to Main Thread to update UI and handle other tasks. if (i % yieldInterval === 0) { await new Promise(resolve => setTimeout(resolve, 0)) } result.push(threadBlockingEnabled ? blockingTask(10) : data[i]) } return result } Vexamos o que está a pasar aquí: Liña 3: Unha promesa é creada e o seu executor execútase inmediatamente, programando unha setTimeout() con atraso cero. A chamada de volta do timeout (que resolve a promesa) engádese ao final da cola da macrotask. Debido á espera, o resto da función async está parado. Tecnicamente, esta continuación engádese á cola da microtask, esperando que a promesa resuelva. O motor JavaScript comproba o Stack de chamada - unha vez que está baleiro, o Loop de eventos entra. En primeiro lugar, mira á cola da microtask - pero xa que a promesa non está resolta aínda, non hai nada que executar. Entón, o Loop de eventos elixe a macrotask da cola (no noso exemplo, é o Time setout() de volta), executa o traballo, e isto resolve a Prom Liña 9: Calcúlase a frecuencia coa que se quere rendir ao tema principal, aproximadamente cada 25% do traballo. Liñas 13-15: Dentro do loop, se se cumpre a condición para o intervalo de rendemento, a execución é transferida ao thread principal, é dicir, a técnica setTimeout() repítese, permitindo que o navegador proceda a interaccións do usuario ou redrive a interface. Basicamente, este enfoque funciona - é relativamente sinxelo e mellora a capacidade de resposta. Pero hai compromisos. Pón tarefas ao final da cola da macrotask, e calquera cousa que xa estea nesa cola pode atrasar a súa continuación. setTimeout() Por exemplo, digamos que algunha outra parte da páxina usa Executar tarefas regularmente: setInterval() setInterval(() => { /* Another heavy work... */ }) async function heavyWork() { // Yield to Main Thread to avoid UI blocking before heavy work await new Promise(resolve => setTimeout(resolve, 0)) const data = Array.from({ length: 200 }, (_, i) => i) const result = [] // Interval at which execution will be yielded to the main thread (approx. ~ 25%). const yieldInterval = Math.ceil(data.length / 4) for (let i = 0; i < data.length; i++) { // Yield control to Main Thread to update UI and handle other tasks. if (i % yieldInterval === 0) { await new Promise((resolve, reject) => setTimeout(resolve, 0)) } result.push(threadBlockingEnabled ? blockingTask(10) : data[i]) } return result } Agora a súa propia tarefa - a seguinte peza de función - pode ser atrasado por un ou máis destes intervalo de chamadas de volta. O navegador só executa o que está a continuación na liña, e non controla a orde. Unha especie de permítelle rendir, non sabe exactamente cando vai obter o control de volta. heavyWork() setTimeout() Hai outras maneiras de abordar a situación. función, que permite programar o traballo xusto antes da próxima repaint. , e ten desvantaxes similares. ou que executa o seu código durante un tempo inútil do navegador. Non é moi unha alternativa, pero é bo para o fondo, o traballo menos importante, o que axuda ao fío principal a ser libre para tarefas máis críticas. En xeral, poderíamos discutir outras estratexias para resolver e previr tales problemas. trae á mesa. requestAnimationFrame() setTimeout() requestIdleCallback() scheduler.yield() Páxina oficial.yield( – é unha forma moderna de pausar a execución, e render control ao fío principal, o que permite ao navegador realizar calquera traballo pendente de alta prioridade, e despois continuar a execución desde onde deixou. a expresión é alcanzada, a execución da función actual na que foi chamada é suspendida, e dá control ao fío principal, rompendo, ou parando, a tarefa actual.A continuación da función, é dicir, a execución da parte restante dela, desde onde deixou de executarse, é unha microtarefa separada, recentemente programada no Loop de eventos. scheduler.yield() await scheduler.yield() A beleza de A continuación, a continuación da permanece na fronte da cola, e está programado para correr todas as outras tarefas non esenciais que foron agardadas.A principal diferenza da O enfoque é que con , estas continuidades normalmente se executan despois de calquera nova tarefa que xa estivese en cola, o que potencialmente causa longos atrasos entre a rendibilidade ao fío principal e a súa finalización. scheduler.yield() scheduler.yield() BEFORE setTimeout() setTimeout() O seguinte diagrama ilustra como se comparan os tres enfoques na práctica: In the first example, without yielding to the main thread: At first, the long " " runs uninterrupted, blocking the main thread and UI accordingly. Then, a user event is processed – a button click triggered during the execution of " ". And finally, " " is executed – callback scheduled earlier or during the execution of the long task. Task 1 Task 1 Task 2 setTimeout() In the second example, using as a yielding to the main thread: The execution queue is different. At first, the long " " runs. Then, when the yield to the main thread happens, " " pauses to let the browser breathe, and the button click is processed. But after the button click is processed, the callback will be executed first, which could have been scheduled in advance or during the execution of " ". And finally, only after that, the continuation of " " will be executed. setTimeout() Task 1 Task 1 setTimeout() Task 1 Task 1 In the last example, using : After the long " " has been paused and the user click event has been processed, then the continuation of " " is prioritized and runs before any queued tasks. scheduler.yield() Task 1 Task 1 setTimeout() In summary, is a more intelligent and predictable way to give the main thread breathing room. It avoids the risk of your code being pushed too far back in the queue and helps maintain performance and responsiveness, especially in complex applications. scheduler.yield() As prioridades. Entón, o que causa tal diferenza de comportamento? É todo sobre prioridades! Como desenvolvedores, xeralmente non pensamos na orde de execución de tarefas no ciclo de eventos en termos de prioridades. e Pero se miras máis profundamente, notarás que tamén hai prioridades implícitas en xogo. Por exemplo, un manipulador de botóns, disparado pola acción do usuario, normalmente executará antes dun A Coruña, aínda que ambos os dous Como se mencionou anteriormente, É unha parte do – unha interface extensa e rica en recursos que merece a súa propia discusión completa separada e está claramente máis aló do alcance desta conversa. Con todo, é importante mencionar unha das súas características clave: a introdución dun modelo de prioridade de tarefas claro. A API de planificación de tarefas prioritarias simplemente fai que estas prioridades sexan explícitas, o que facilita determinar que tarefas se executarán primeiro e permite axustar as prioridades para cambiar a orde de execución, se fose necesario. microtasks macrotasks setTimeout() macrotasks scheduler.yield() Prioritized Task Scheduling API " " – The highest priority tasks that directly affect user interaction, such as handling clicks, taps, and critical UI operations. user-blocking "Visible para o usuario" - Tarefas que afectan á visibilidade da interfaz de usuario ou ao contido, pero non son críticas para a entrada inmediata. Tarefas que non son urxentes e que se poden pospoñer de forma segura sen afectar á experiencia do usuario actual, e que non son visibles para o usuario. polo defecto, Ten unha » “Prioridade” tamén Expoñen o método, designado para programar tarefas cunha prioridade especificada do anterior. Aínda que non vai entrar en detalles sobre este método aquí, vale a pena mencionar que se Foi deseñado desde dentro a herdan a súa prioridade. scheduler.yield() user-visible Prioritized Task Scheduling API postTask() scheduler.yield() postTask() Como se pode usar o calendario.yield(). Unha vez que entenda como funciona todo - os tipos de tarefas, o problema causado por operacións de bloqueo prolongadas e as prioridades, o uso de se fai sinxelo. Pero debe ser usado sabiamente e con debida precaución. Aquí está unha versión actualizada do Funcións Usando Agora, en vez de Só tes que chamar , and the rest part remains unchanged. scheduler.yield() heavyWork() scheduler.yield() setTimeout() await scheduler.yield() async function heavyWork() { // Yield to Main Thread to avoid UI blocking before heavy work await scheduler.yield() const data = Array.from({ length: 200 }, (_, i) => i) const result = [] // Interval at which execution will be yielded to the main thread (approx. ~ 25%). const yieldInterval = Math.ceil(data.length / 4) for (let i = 0; i < data.length; i++) { // Yield control to Main Thread to update UI and handle other tasks. if (i % yieldInterval === 0) { await scheduler.yield() } result.push(threadBlockingEnabled ? blockingTask(10) : data[i]) } return result } Agora, cando un usuario comeza a Funcións Usando , a diferenza é inmediatamente perceptíbel. primeiro, o " " botón non se pega, e en segundo lugar, o usuario fai clic en eventos na " Os botóns son procesados con éxito, o que non bloquea a interacción do usuario coa páxina. heavyWork() scheduler.yield() OK Log É dicir, en primeiro lugar, o Función foi lanzado, e o botón foi re-rendered sen pegar.Mentres esta tarefa pesada estaba a ser executado, o usuario presionou o " O evento foi procesado con éxito e os datos foron impresos na consola. A función continuou, e o seu resultado final foi impreso na consola. Despois da finalización, o usuario presionou a " En resumo, pode dar o seu navegador unha pausa con só unha liña. heavyWork() Log heavyWork() Log Unha demo. Descrición da funcionalidade. Agora que explorou a teoría, imos ir á práctica e ver unha demostración de traballo real. Esta é unha aplicación bancaria simulada. Por suposto, é ficticia e simplificada, pero captura o suficiente da complexidade do mundo real para axudarche a entender como o bloqueo do fío principal afecta á interactividade, e como Pode axudar scheduler.yield() Aquí está o que o usuario ve na interface: – By default, the account balance is hidden behind a placeholder of asterisks. This is a familiar pattern in real banking apps, where sensitive information is hidden unless explicitly revealed by the user. A button labeled " " toggles visibility. Balance section Show balance – A visual representation of a bank card, shown front side by default, where some details are displayed: card type in the top left corner, last 4 digits of the card, the cardholder's name, and payment system, at the bottom right corner of the card. There are two buttons to the right of the card: Bank card – which flips the card when clicked. The back side of the card reveals sensitive card data like its full number, expiration date, and CVV code. Although the card number is generally not considered private information, some applications still prefer not to show the full number by default, but only if the user initiates it. However, I know and even use banks that generally do not allow you to see the bank card number in the application. Show card details – by clicking this button, this feature supposedly generates a list of transactions on the card and displays them in the table below. It imitates the real functionality where users can generate reports on bank card transactions. In reality, these reports can be complex tables with many customizable filters and the ability to download the report as a file. Such operations might involve heavy computations, process a huge amount of data, making them resource-intensive and time-consuming. For the sake of the demo, it's simplified. Under the hood, the " " button triggers the previously discussed function, which simply blocks the main thread using the function, which was also discussed above. After that, static mock transaction data is simply rendered into the table. Generate report Generate report heavyWork() blockingTask() O comportamento da aplicación pode ser personalizado usando as diferentes opcións no panel de configuración da esquerda. pode ter notado a súa versión simplificada en capturas de pantalla anteriores. Agora é o momento de explicar o que fai: Principal Thread blocking – determina se o Principal Thread será bloqueado.En realidade, cando esta opción está habilitada, a función blockingTask() é executada. Scheduler.yield() – Rexistra se se usa scheduler.yield() Lonxitude de matriz de datos - Controla cantos elementos son iterados pola función heavyWork(). Canto máis elementos, máis tempo leva. Duración do tempo de bloqueo - Especifica cantos milisegundos leva cada elemento da matriz para procesar. Intervalo de rendemento – Define a frecuencia coa que se chama scheduler.yield() como porcentaxe de progreso a través da matriz. É dicir, canto menor sexa este número, canto máis frecuentemente será chamado. En exemplos anteriores, usamos unha matriz de 200 elementos cun atraso de 10 ms e un intervalo de 25% – un bo equilibrio para o impacto visible sen retraso excesivo. Con conxuntos de datos máis grandes, un intervalo máis pequeno é a miúdo mellor. Unha demostración. Despois de ordenar toda a funcionalidade e configuración, imos pasar por un escenario de uso real e ver como bloquear o fío principal afecta á experiencia do usuario. Bloqueo e desactivación Tamén aumentamos un pouco a lonxitude da matriz, polo que a operación pesada leva máis tempo, dándonos tempo para observar os efectos. detrás das escenas, isto desencadea a Función, que procesa 1000 elementos, onde cada elemento leva 10 milisegundos. Main Thread scheduler.yield() Generate report heavyWork() Mirade o que pasou: a " botón permanece atrapado, non se desprende, e a interfaz de usuario non se repite. Mentres o informe está a ser xerado, o usuario intenta premer na " “ entón ” " botóns, pero nada responde. A interface está completamente conxelada, non hai animación, ningún feedback, ningún sentido de progreso. Este é un exemplo clásico dunha mala experiencia do usuario. A aplicación aparece conxelada, aínda que tecnicamente aínda funciona. O usuario non sabe se esperar ou recargar a páxina. Generate report Show card details Show balance abordar as súas deficiencias utilizando axustando algunhas configuracións. Aquí está como é a configuración agora: aínda está bloqueado. Esta vez, a opción de usar A lonxitude da matriz aumenta lixeiramente, só para a claridade. O tempo de bloqueo permanece o mesmo, 10 milisegundos. O intervalo de resposta redúcese ao 5% para unha resposta máis suave, xa que se aumentou a lonxitude da matriz. scheduler.yield() Main Thread scheduler.yield() scheduler.yield() E agora coa configuración actualizada, o mesmo fluxo de usuario parece completamente diferente. " botón foi clicado, re-render correctamente, e a animación de carga aparece. Mentres o informe está a ser xerado, o usuario interacciona con éxito coa interface de usuario: poden virar a tarxeta e cambiar o saldo. A aplicación permanece responsivo, aínda que as animacións son un pouco menos suave, é un gran paso adiante en comparación co conxelamento anterior. Esta é unha experiencia moito mellor. O usuario é informado, en control, e non deixa adiviñar se a aplicación está a funcionar. Por suposto, a implementación real pode optimizarse aínda máis, pero mesmo nesta forma simple, a diferenza é sorprendente. Generate report scheduler.yield() Conclusion. Entón, hoxe aprendeu sobre dar o seu navegador unha pausa, a importancia de ceder ao para realizar tarefas de maior prioridade, e as vantaxes e desvantaxes destas técnicas. ten outras capacidades que non foron cubertas neste artigo. pero o meu obxectivo era darche unha base sólida, o suficiente para comezar a experimentar, e o suficiente para comezar a pensar doutro xeito sobre como o teu código xoga co navegador. Grazas por ler, e dar o teu navegador unha pausa de cando en vez! Main Thread Prioritized Task Scheduling API Ligazóns útiles. Demo en liña – https://let-your-browser-take-a-breather.onrender.com/ Demo repositorio de GitHub – https://github.com/WOLFRIEND/let_your_browser_take_a_breather Diagrama – https://drive.google.com/file/d/1FLKKPaseyypE3pVXXn7Cj0aWac3rCayn/view