Fiquei com a impressão de que o JavaScript sempre foi assíncrono. No entanto, eu aprendi que há situações em que não existe (ou seja, manipulações DOM). Existe uma boa referência sobre quando será síncrono e quando será assíncrono? O jQuery afeta isso?
javascript
jquery
Brian
fonte
fonte
Respostas:
O JavaScript é sempre síncrono e de thread único. Se você estiver executando um bloco de código JavaScript em uma página, nenhum outro JavaScript nessa página será atualmente executado.
JavaScript é assíncrono apenas no sentido em que pode fazer, por exemplo, chamadas de Ajax. A chamada do Ajax interromperá a execução e outro código poderá ser executado até que a chamada retorne (com êxito ou não), momento em que o retorno de chamada será executado de forma síncrona. Nenhum outro código estará em execução neste momento. Não interromperá nenhum outro código atualmente em execução.
Os temporizadores de JavaScript operam com esse mesmo tipo de retorno de chamada.
A descrição de JavaScript como assíncrono talvez seja enganosa. É mais preciso dizer que o JavaScript é síncrono e de thread único com vários mecanismos de retorno de chamada.
O jQuery tem uma opção nas chamadas do Ajax para torná-las sincronizadas (com a
async: false
opção). Os iniciantes podem ficar tentados a usar isso incorretamente, pois permite um modelo de programação mais tradicional ao qual se pode estar mais acostumado. A razão pela qual é problemático é que essa opção bloqueia todo o JavaScript na página até sua conclusão, incluindo todos os manipuladores de eventos e cronômetros.fonte
O JavaScript é único e possui um modelo de execução síncrona. Encadeamento único significa que um comando está sendo executado por vez. Síncrono significa um de cada vez, ou seja, uma linha de código está sendo executada ao mesmo tempo para que o código apareça. Então, em JavaScript, uma coisa está acontecendo de cada vez.
Contexto de Execução
O mecanismo JavaScript interage com outros mecanismos no navegador. Na pilha de execução do JavaScript, há um contexto global na parte inferior e, quando invocamos funções, o mecanismo JavaScript cria novos contextos de execução para as respectivas funções. Quando a função chamada sai, seu contexto de execução é exibido na pilha e o próximo contexto de execução é exibido e assim por diante ...
Por exemplo
No código acima, um contexto de execução global será criado e, nesse contexto
var one
, será armazenado e seu valor será 1 ... quando a chamada xyz () for chamada, um novo contexto de execução será criado e se definimos alguma variável na função xyz, essas variáveis seriam armazenadas no contexto de execução de xyz (). Na função xyz, invocamos abc () e, em seguida, o contexto de execução abc () é criado e colocado na pilha de execução ... Agora, quando abc () termina, seu contexto é retirado da pilha, o contexto xyz () é retirado de empilhar e, em seguida, o contexto global será exibido ...Agora, sobre retornos de chamada assíncronos; assíncrono significa mais de um de cada vez.
Assim como a pilha de execução, há a fila de eventos . Quando queremos ser notificados sobre algum evento no mecanismo JavaScript, podemos ouvi-lo, e esse evento é colocado na fila. Por exemplo, um evento de solicitação do Ajax ou evento de solicitação de HTTP.
Sempre que a pilha de execução estiver vazia, como mostrado no exemplo de código acima, o mecanismo JavaScript verifica periodicamente a fila de eventos e verifica se há algum evento a ser notificado. Por exemplo, na fila, havia dois eventos, uma solicitação ajax e uma solicitação HTTP. Ele também procura ver se existe uma função que precise ser executada nesse gatilho de evento ... Portanto, o mecanismo JavaScript é notificado sobre o evento e conhece a respectiva função a ser executada nesse evento ... Portanto, o mecanismo JavaScript chama o função manipulador, no caso de exemplo, por exemplo, AjaxHandler () será invocado e, como sempre, quando uma função é invocada, seu contexto de execução é colocado no contexto de execução e agora a execução da função termina e a solicitação de evento ajax também é removida da fila de eventos ... Quando AjaxHandler () termina, a pilha de execução está vazia, portanto, o mecanismo novamente analisa a fila de eventos e executa a função de manipulador de eventos da solicitação HTTP, que foi a próxima na fila. É importante lembrar que a fila de eventos é processada apenas quando a pilha de execução está vazia.
Por exemplo, consulte o código abaixo, explicando a pilha de execução e a manipulação da fila de eventos pelo mecanismo Javascript.
E
Agora execute a página da web, clique na página e veja a saída no console. A saída será
O mecanismo JavaScript está executando o código de forma síncrona, conforme explicado na parte do contexto de execução, o navegador está colocando as coisas de forma assíncrona na fila de eventos. Portanto, as funções que levam muito tempo para serem concluídas podem interromper a manipulação de eventos. Coisas que acontecem em um navegador, como eventos, são tratadas dessa maneira por JavaScript; se houver um ouvinte em execução, o mecanismo executará quando a pilha de execução estiver vazia. Como os eventos são processados na ordem em que ocorrem, a parte assíncrona é sobre o que está acontecendo fora do mecanismo, ou seja, o que o mecanismo deve fazer quando esses eventos externos acontecerem.
Portanto, o JavaScript é sempre síncrono.
fonte
O JavaScript é de thread único e o tempo todo você trabalha em uma execução de fluxo de código síncrono normal.
Bons exemplos do comportamento assíncrono que o JavaScript pode ter são eventos (interação do usuário, resultados de solicitação do Ajax, etc.) e timers, basicamente ações que podem ocorrer a qualquer momento.
Eu recomendo que você dê uma olhada no seguinte artigo:
Esse artigo ajudará você a entender a natureza de thread único do JavaScript e como os cronômetros funcionam internamente e como funciona a execução assíncrona do JavaScript.
fonte
Para alguém que realmente entende como o JS funciona, essa pergunta pode parecer ruim, no entanto, a maioria das pessoas que usa o JS não tem um nível tão profundo de insight (e não necessariamente precisa dele) e, para eles, esse é um ponto bastante confuso. tente responder dessa perspectiva.
JS é síncrono na maneira como seu código é executado. cada linha é executada somente após a linha antes de ser concluída e se essa linha chama uma função após a conclusão ect ...
O principal ponto de confusão decorre do fato de que seu navegador é capaz de dizer ao JS para extrair mais código a qualquer momento (veja como você pode extrair mais código JS em uma página do console). Como exemplo, o JS tem funções de retorno de
GET
chamada cujo objetivo é permitir que o JS se comporte de forma assíncrona, para que outras partes do JS possam ser executadas enquanto aguarda uma função JS executada (ou seja, uma chamada) retornar uma resposta, o JS continuará em execução até o navegador tem uma resposta nesse ponto, o loop de eventos (navegador) executará o código JS que chama a função de retorno de chamada.Como o loop de eventos (navegador) pode inserir mais JS para ser executado em qualquer ponto nesse sentido, o JS é assíncrono (as principais coisas que farão com que o navegador insira o código JS são tempos limite, retornos de chamada e eventos)
Espero que isso seja claro o suficiente para ajudar alguém.
fonte
Definição
O termo "assíncrono" pode ser usado com significados ligeiramente diferentes, resultando em respostas aparentemente conflitantes aqui, enquanto na verdade não são. A Wikipedia sobre Assincronia tem esta definição:
código não JavaScript pode enfileirar esses eventos "externos" para algumas das filas de eventos do JavaScript. Mas isso é o mais longe possível.
Sem Preempção
Não há interrupção externa da execução do código JavaScript para executar outro código JavaScript no seu script. Partes do JavaScript são executadas uma após a outra, e a ordem é determinada pela ordem dos eventos em cada fila de eventos e pela prioridade dessas filas.
Por exemplo, você pode ter certeza absoluta de que nenhum outro JavaScript (no mesmo script) será executado enquanto o seguinte trecho de código estiver em execução:
Em outras palavras, não há preempção no JavaScript. O que quer que esteja nas filas de eventos, o processamento desses eventos terá que esperar até que esse trecho de código seja executado até a conclusão. A especificação EcmaScript diz na seção 8.4 Trabalhos e filas de trabalhos :
Exemplos de assincronia
Como outros já escreveram, há várias situações em que a assincronia entra em jogo no JavaScript, e sempre envolve uma fila de eventos, que só pode resultar na execução do JavaScript quando não há outro código JavaScript em execução:
setTimeout()
: o agente (por exemplo, navegador) colocará um evento em uma fila de eventos quando o tempo limite expirar. O monitoramento da hora e a colocação do evento na fila acontecem por código não JavaScript, e você pode imaginar que isso acontece paralelamente à execução potencial de algum código JavaScript. Mas o retorno de chamada fornecidosetTimeout
somente pode ser executado quando o código JavaScript atualmente em execução foi executado e a fila de eventos apropriada está sendo lida.fetch()
: o agente usará funções do SO para executar uma solicitação HTTP e monitorar qualquer resposta recebida. Novamente, essa tarefa não JavaScript pode ser executada em paralelo com algum código JavaScript que ainda está em execução. Mas o procedimento de resolução da promessa, que resolverá a promessa retornada porfetch()
, só poderá ser executado quando o JavaScript atualmente em execução for concluído.requestAnimationFrame()
: o mecanismo de renderização do navegador (não JavaScript) colocará um evento na fila JavaScript quando estiver pronto para executar uma operação de pintura. Quando o evento JavaScript é processado, a função de retorno de chamada é executada.queueMicrotask()
: coloca imediatamente um evento na fila de microtask. O retorno de chamada será executado quando a pilha de chamadas estiver vazia e esse evento for consumido.Existem muitos outros exemplos, mas todas essas funções são fornecidas pelo ambiente host, não pelo EcmaScript principal. Com o EcmaScript básico, você pode colocar de forma síncrona um evento em uma fila de tarefas do Promise
Promise.resolve()
.Construções de linguagem
EcmaScript fornece várias construções de linguagem para suportar o padrão de assincronia, tais como
yield
,async
,await
. Mas não se engane: nenhum código JavaScript será interrompido por um evento externo. A "interrupção" queyield
eawait
parecem fornecer é apenas uma maneira controlada, predefinido de retornar de uma chamada de função e restaurar seu contexto de execução, mais tarde, seja por código JS (no caso deyield
), ou a fila de eventos (no caso deawait
)Tratamento de eventos DOM
Quando o código JavaScript acessa a API do DOM, isso pode, em alguns casos, fazer com que a API do DOM acione uma ou mais notificações síncronas. E se o seu código tiver um manipulador de eventos ouvindo isso, ele será chamado.
Isso pode parecer uma simultaneidade preventiva, mas não é: assim que os manipuladores de eventos retornarem, a API DOM também retornará e o código JavaScript original continuará.
Em outros casos, a API do DOM enviará apenas um evento na fila de eventos apropriada e o JavaScript o buscará assim que a pilha de chamadas for esvaziada.
Veja eventos síncronos e assíncronos
fonte
É síncrono em todos os casos.
Exemplo de thread de bloqueio com
Promises
:A saída será:
fonte