[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Execution_model [Back]  [Original]

Modelo de Concorrncia e Event Loop - JavaScript | MDN

Esta pgina foi traduzida do ingls pela comunidade. Saiba mais e junte-se comunidade MDN Web Docs.

View in English Always switch to English

Modelo de Concorrncia e Event Loop

O JavaScript possui um modelo de concorrncia baseado em um event loop (lao de eventos), em portugus), responsvel pela execuo do cdigo, coleta e processamento de eventos e execuo de subtarefas enfileiradas. Este modelo bem diferente de outras linguagens, como C ou Java, por exemplo.

In this article

Conceitos de runtime (tempo de execuo)

Os prximos tpicos iro explicar teoricamente o modelo. Interpretadores modernos de JavaScript implementam e otimizam fortemente as semnticas descritas.

Representao visual

Stack, heap, queue [Stack, heap, queue]

Pilha (Stack)

As chamadas de funes criam uma pilha de frames (quadros).

js
function foo(b) {
  let a = 10;
  return a + b + 11;
}

function bar(x) {
  let y = 3;
  return foo(x * y);
}

const baz = bar(7); // atribui 42 a baz

Ordem das operaes:

  1. Quando chamamos a funo bar, o primeiro frame criado contendo argumentos e variveis locais de bar.
  2. Quando a funo bar chama foo, o segundo frame criado e colocado no topo da pilha, contendo os argumentos e as variveis locais de foo.
  3. Quando foo retorna, o frame do topo removido da pilha (deixando apenas o frame da chamada de bar).
  4. Quando bar retorna, a pilha fica vazia.

Note que os argumentos e variveis locais podem continuar existindo, pois so armazenados fora da pilha de forma que podem ser acessados por quaisquer funes aninhadas muito depois de sua funo externa ter retornado.

Acervo (Heap)

Os objetos so alocados em um heap (acervo), que apenas um nome para denotar uma grande regio no estruturada da memria.

Fila (Queue)

O runtime do JavaScript contm uma fila de mensagens, que uma lista de mensagens a serem processadas. Cada mensagem associada a uma funo, que chamada para lidar com a mensagem.

Em algum ponto durante o event loop (lao de eventos), o runtime comea a manipular as mensagens na fila, comeando pela mais antiga. Para fazer isso, a mensagem removida da fila e sua funo correspondente chamada com a mensagem como um parmetro de input (entrada). Como de costume, chamar uma funo cria um novo frame (quadro) na pilha para uso dessa funo.

O processamento de funes continua at que a pilha fique novamente vazia, ento o event loop processar a prxima mensagem na fila (se houver uma).

Lao de Eventos (Event loop)

O Event loop tem esse nome por causa da forma que normalmente implementado, que se assemelha a:

js
while (queue.waitForMessage()) {
  queue.processNextMessage();
}

queue.waitForMessage aguarda, de maneira sncrona, receber uma mensagem (se no houver nenhuma j disponvel esperando para ser tratada).

Processamento Completo ("Run-to-completion")

Cada mensagem processada completamente antes de outra mensagem ser processada. Isso oferece um bom fundamento ao pensar sobre o seu software, incluindo o fato de que, independente de quando uma funo executada, ela no pode ser interrompida e, portanto, ser executada por completo antes que outro cdigo rode (e modifique dados manipulveis pela funo). Isso diferente do C, por exemplo, no qual uma funo que est sendo executada em uma thread (um fluxo de execuo), pode ser interrompida a qualquer momento para executar um outro cdigo em outra thread.

Um aspecto negativo deste modelo que se uma mensagem levar muito tempo para ser finalizada, a aplicao web ficar indisponvel para processar as interaes do usurio, como cliques ou rolagens. O navegador mitiga este problema atravs do aviso: "Um script desta pgina pode estar ocupado, ou parou de responder". Uma boa prtica a seguir fazer o processamento de mensagens curtas, e, se possvel, dividir uma longa mensagem em mltiplas mensagens menores.

Adicionando mensagens

Nos navegadores, as mensagens so adicionadas a qualquer momento que um evento acionado se este possuir um listener (ouvinte). Caso no haja, o evento ser ignorado. Assim, um clique em um elemento com um manipulador de eventos de clique adicionar uma mensagem, como qualquer outro evento.

A funo setTimeout chamada com 2 argumentos: uma mensagem para adicionar fila (queue) e um valor em tempo (opcional, o padro 0). O valor de tempo (time value) representa o intervalo (mnimo) com que a mensagem ser realmente enviada fila. Se no houver outra mensagem na fila, a mensagem ser processada logo aps o intervalo. No entanto, caso haja mensagens, a mensagem setTimeout ter que esperar at que outras mensagens sejam processadas. Por esse motivo, o segundo argumento indica um tempo mnimo e no um tempo garantido.

Aqui est um exemplo que demonstra esse conceito (setTimeout no executado imediatamente aps o temporizador expirar):

js
const s = new Date().getSeconds();

setTimeout(function () {
  // imprime "2", o que significa que o callback no  chamado imediatamente aps 500 milissegundos.
  console.log("Ran after " + (new Date().getSeconds() - s) + " seconds");
}, 500);

while (true) {
  if (new Date().getSeconds() - s >= 2) {
    console.log("Good, looped for 2 seconds");
    break;
  }
}

Intervalos de zero segundos

O intervalo zero no significa, necessariamente, que o callback ser disparado aps zero milissegundos. Chamar setTimeout com um intervalo de 0 (zero) milissegundos no executa a funo do callback aps intervalo dado.

A execuo depende do nmero de mensagens em espera na fila. No exemplo abaixo, a mensagem ''this is just a message'' ser escrita no console antes que a mensagem do callback seja processada, porque, como informado previamente, o intervalo definido na funo indica o tempo mnimo necessrio para que a aplicao processe a requisio e no o tempo exato de processamento.

Basicamente, setTimeout precisa esperar que todo o cdigo das mensagens enfileiradas seja concludo, mesmo que voc tenha especificado um tempo limite especfico para o seu setTimeout.

js
(function () {
  console.log("this is the start");

  setTimeout(function cb() {
    console.log("Callback 1: this is a msg from call back");
  }); // tem um valor de tempo padro de 0

  console.log("this is just a message");

  setTimeout(function cb1() {
    console.log("Callback 2: this is a msg from call back");
  }, 0);

  console.log("this is the end");
})();

// "this is the start"
// "this is just a message"
// "this is the end"
// "Callback 1: this is a msg from call back"
// "Callback 2: this is a msg from call back"

Mltiplos runtimes comunicando-se em conjunto

Um web worker ou um iframe com uma diferente origem (cross-origin) tem seu prprio stack, heap e queue de messagens. Dois runtimes distintos s podem se comunicar por meio do envio de mensagens via mtodo postMessage. Este mtodo adiciona uma mensagem ao outro runtime, se este escutar os eventos de message.

Sem bloqueio

Uma propriedade muito interessante do modelo event loop que o JavaScript, ao contrrio de muitas outras linguagens, nunca bloqueia. A manipulao de E/S (I/O) tipicamente realizada atravs de eventos e callbacks. Portanto, quando uma aplicao est esperando pelo retorno de uma consulta do IndexedDB ou de uma requisio XHR, ela ainda pode processar outras coisas, como as aes do usurio.

Excees de legado existem, como por exemplo, alert ou XHR sncrono, mas considerado uma boa prtica evit-los. Tome cuidado, excees a exceo existem (mas geralmente so, mais do que qualquer coisa, bugs de implementao).

Veja tambm


Web Proxy Viewer  |  New URL  |  Original Page