"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > SetTimeout não é o mesmo que você pensa

SetTimeout não é o mesmo que você pensa

Publicado em 19/08/2024
Navegar:473

Quando os desenvolvedores encontram setTimeout pela primeira vez em JavaScript, muitas vezes parece uma ferramenta simples para atrasar a execução de funções. No entanto, entender como setTimeout interage com o tempo de execução do JavaScript e o loop de eventos pode revelar alguns comportamentos inesperados, especialmente em determinadas condições. E não é apenas setTimeout; complexidades semelhantes surgem com setInterval e outras funções assíncronas também.

O ciclo de eventos: uma breve visão geral
JavaScript é de thread único, o que significa que só pode executar um trecho de código por vez. Apesar disso, o loop de eventos permite que o JavaScript execute operações sem bloqueio. Ele consegue isso descarregando tarefas como temporizadores, solicitações de rede ou operações de E/S para o navegador ou API Node.js. Depois que essas tarefas são concluídas, suas funções de retorno de chamada são recolocadas na fila do loop de eventos para execução.

SetTimeout is Not the Same as You Think

Como funciona setTimeout
Ao chamar setTimeout, você solicita ao mecanismo JavaScript que execute uma função após um período especificado. Isso é feito adicionando a função de retorno de chamada à fila do loop de eventos. Entretanto, o atraso especificado é o tempo mínimo que o mecanismo deve esperar antes de adicionar o retorno de chamada à fila, e não um tempo de execução garantido. Veja como funciona em detalhes:

  1. Chamada inicial: quando setTimeout é invocado com uma função de retorno de chamada e um atraso, o mecanismo JavaScript registra isso no ambiente de API da Web fornecido pelo navegador ou Node.js.

  2. Timer: a API da Web inicia um cronômetro para o atraso especificado. Durante esse período, a pilha de chamadas principal continua a executar qualquer código síncrono que segue a chamada setTimeout.

  3. Callback Queuing: depois que o cronômetro expira, a API da Web não executa imediatamente o retorno de chamada. Em vez disso, ele move a função de retorno de chamada para a fila de eventos.

  4. Event Loop: O loop de eventos, que monitora continuamente a pilha de chamadas e a fila de eventos, entra em ação. Se a pilha de chamadas estiver vazia, o que significa que não há tarefas em execução no momento, o loop de eventos pega a primeira função da fila de eventos e a coloca na pilha de chamadas para execução.

  5. Execução: A função de retorno de chamada é finalmente executada quando atinge o topo da pilha de chamadas.

É importante observar que se a pilha de chamadas estiver ocupada com outras tarefas quando o cronômetro expirar, poderá haver atrasos adicionais antes que a função de retorno de chamada seja executada. Isso ocorre porque o loop de eventos deve esperar até que a pilha de chamadas esteja limpa antes de poder processar a função de retorno de chamada da fila de eventos.

SetTimeout is Not the Same as You Think


O problema do bloqueio
Um mal-entendido comum é presumir que setTimeout sempre executará o retorno de chamada após o atraso exato especificado. Se o loop de eventos for bloqueado por código síncrono, como um loop infinito ou computação de longa duração, o retorno de chamada não será executado até que o loop de eventos esteja livre.

Considere o seguinte cenário:

console.log('Program started at: '   new Date().toLocaleTimeString());

const programStartTime = Date.now();

function blockExecutionForThirtySeconds() {
  while (true) {
    const currentTime = Date.now();
    if (currentTime - programStartTime > 30000) {
      console.log('Blocking execution completed after 30 seconds...');
      return true;
    }
  }
}

console.log('Setting setTimeout for 1 second.');
setTimeout(() => {
  console.log('setTimeout executed after 30 seconds instead of 1 second: '   new Date().toLocaleTimeString());
}, 1000);

blockExecutionForThirtySeconds();

Neste exemplo, a função blockExecutionForThirtySeconds bloqueia o loop de eventos com um loop infinito que é executado por 30 segundos. Mesmo que setTimeout esteja definido para ser executado após 1 segundo, ele só será executado após a conclusão de blockExecutionForThirtySeconds, ou seja, após 30 segundos.

SetTimeout is Not the Same as You Think

Implicações no mundo real
Compreender esse comportamento é crucial para desenvolvedores, especialmente ao escrever código que envolve tempos limite, intervalos ou processamento assíncrono. A má compreensão de como setTimeout funciona pode levar a problemas de desempenho e bugs difíceis de rastrear. Se um trecho de código realizar cálculos pesados ​​ou tarefas de longa execução e bloquear o loop de eventos, todos os retornos de chamada setTimeout, resoluções de promessas e outras operações assíncronas serão adiadas até que o loop de eventos esteja livre.

Conclusão
setTimeout é uma ferramenta poderosa em JavaScript para atrasar a execução de código, mas é importante entender suas nuances. O atraso especificado é o tempo mínimo de espera antes que a função possa ser colocada na fila para execução. O tempo real de execução depende do estado do loop de eventos. Dominar as operações assíncronas e o gerenciamento de loop de eventos é fundamental para escrever aplicativos JavaScript eficientes e responsivos.

Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/mrrishimeena/settimeout-is-not-the-same-as-you-think-44ep?1 Se houver alguma violação, entre em contato com [email protected] para excluir isto
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3