From 68fc8e96a9629e73469ed457abd955e548ec670c Mon Sep 17 00:00:00 2001 From: Florian Merz Date: Thu, 11 Feb 2021 14:49:58 +0100 Subject: unslug pt-br: move --- .../choosing_the_right_approach/index.html | 523 +++++++++++++++++++++ .../javascript/asynchronous/conceitos/index.html | 155 ------ .../javascript/asynchronous/concepts/index.html | 155 ++++++ .../escolhendo_abordagem_correta/index.html | 523 --------------------- .../javascript/asynchronous/introducing/index.html | 283 +++++++++++ .../introdu\303\247\303\243o/index.html" | 283 ----------- 6 files changed, 961 insertions(+), 961 deletions(-) create mode 100644 files/pt-br/learn/javascript/asynchronous/choosing_the_right_approach/index.html delete mode 100644 files/pt-br/learn/javascript/asynchronous/conceitos/index.html create mode 100644 files/pt-br/learn/javascript/asynchronous/concepts/index.html delete mode 100644 files/pt-br/learn/javascript/asynchronous/escolhendo_abordagem_correta/index.html create mode 100644 files/pt-br/learn/javascript/asynchronous/introducing/index.html delete mode 100644 "files/pt-br/learn/javascript/asynchronous/introdu\303\247\303\243o/index.html" (limited to 'files/pt-br/learn/javascript/asynchronous') diff --git a/files/pt-br/learn/javascript/asynchronous/choosing_the_right_approach/index.html b/files/pt-br/learn/javascript/asynchronous/choosing_the_right_approach/index.html new file mode 100644 index 0000000000..254bc41a99 --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/choosing_the_right_approach/index.html @@ -0,0 +1,523 @@ +--- +title: Escolhendo a abordagem correta +slug: Learn/JavaScript/Asynchronous/Escolhendo_abordagem_correta +translation_of: Learn/JavaScript/Asynchronous/Choosing_the_right_approach +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}
+ +

To finish this module off, we'll provide a brief discussion of the different coding techniques and features we've discussed throughout, looking at which one you should use when, with recommendations and reminders of common pitfalls where appropriate. We'll probably add to this resource as time goes on.

+ + + + + + + + + + + + +
Prerequisites:Basic computer literacy, a reasonable understanding of JavaScript fundamentals.
Objective:To be able to make a sound choice of when to use different asynchronous programming techniques.
+ +

Asynchronous callbacks

+ +

Generally found in old-style APIs, involves a function being passed into another function as a parameter, which is then invoked when an asynchronous operation has been completed, so that the callback can in turn do something with the result. This is the precursor to promises; it's not as efficient or flexible. Use only when necessary.

+ + + + + + + + + + + + + + + + + + + +
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
NoYes (recursive callbacks)Yes (nested callbacks)No
+ +

Code example

+ +

An example that loads a resource via the XMLHttpRequest API (run it live, and see the source):

+ +
function loadAsset(url, type, callback) {
+  let xhr = new XMLHttpRequest();
+  xhr.open('GET', url);
+  xhr.responseType = type;
+
+  xhr.onload = function() {
+    callback(xhr.response);
+  };
+
+  xhr.send();
+}
+
+function displayImage(blob) {
+  let objectURL = URL.createObjectURL(blob);
+
+  let image = document.createElement('img');
+  image.src = objectURL;
+  document.body.appendChild(image);
+}
+
+loadAsset('coffee.jpg', 'blob', displayImage);
+ +

Pitfalls

+ + + +

Browser compatibility

+ +

Really good general support, although the exact support for callbacks in APIs depends on the particular API. Refer to the reference documentation for the API you're using for more specific support info.

+ +

Further information

+ + + +

setTimeout()

+ +

setTimeout() is a method that allows you to run a function after an arbitrary amount of time has passed.

+ + + + + + + + + + + + + + + + + +
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
YesYes (recursive timeouts)Yes (nested timeouts)No
+ +

Code example

+ +

Here the browser will wait two seconds before executing the anonymous function, then will display the alert message (see it running live, and see the source code):

+ +
let myGreeting = setTimeout(function() {
+  alert('Hello, Mr. Universe!');
+}, 2000)
+ +

Pitfalls

+ +

You can use recursive setTimeout() calls to run a function repeatedly in a similar fashion to setInterval(), using code like this:

+ +
let i = 1;
+setTimeout(function run() {
+  console.log(i);
+  i++;
+
+  setTimeout(run, 100);
+}, 100);
+ +

There is a difference between recursive setTimeout() and setInterval():

+ + + +

When your code has the potential to take longer to run than the time interval you’ve assigned, it’s better to use recursive setTimeout() — this will keep the time interval constant between executions regardless of how long the code takes to execute, and you won't get errors.

+ +

Browser compatibility

+ +

{{Compat("api.WindowOrWorkerGlobalScope.setTimeout")}}

+ +

Further information

+ + + +

setInterval()

+ +

setInterval() is a method that allows you to run a function repeatedly with a set interval of time between each execution. Not as efficient as requestAnimationFrame(), but allows you to choose a running rate/frame rate.

+ + + + + + + + + + + + + + + + + +
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
NoYesNo (unless it is the same one)No
+ +

Code example

+ +

The following function creates a new Date() object, extracts a time string out of it using toLocaleTimeString(), and then displays it in the UI. We then run it once per second using setInterval(), creating the effect of a digital clock that updates once per second (see this live, and also see the source):

+ +
function displayTime() {
+   let date = new Date();
+   let time = date.toLocaleTimeString();
+   document.getElementById('demo').textContent = time;
+}
+
+const createClock = setInterval(displayTime, 1000);
+ +

Pitfalls

+ + + +

Browser compatibility

+ +

{{Compat("api.WindowOrWorkerGlobalScope.setInterval")}}

+ +

Further information

+ + + +

requestAnimationFrame()

+ +

requestAnimationFrame() is a method that allows you to run a function repeatedly, and efficiently, at the best framerate available given the current browser/system. You should, if at all possible, use this instead of setInterval()/recursive setTimeout(), unless you need a specific framerate.

+ + + + + + + + + + + + + + + + + +
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
NoYesNo (unless it is the same one)No
+ +

Code example

+ +

A simple animated spinner; you can find this example live on GitHub (see the source code also):

+ +
const spinner = document.querySelector('div');
+let rotateCount = 0;
+let startTime = null;
+let rAF;
+
+function draw(timestamp) {
+    if(!startTime) {
+        startTime = timestamp;
+    }
+
+    rotateCount = (timestamp - startTime) / 3;
+
+    if(rotateCount > 359) {
+        rotateCount %= 360;
+    }
+
+    spinner.style.transform = 'rotate(' + rotateCount + 'deg)';
+
+    rAF = requestAnimationFrame(draw);
+}
+
+draw();
+ +

Pitfalls

+ + + +

Browser compatibility

+ +

{{Compat("api.Window.requestAnimationFrame")}}

+ +

Further information

+ + + +

Promises

+ +

Promises are a JavaScript feature that allows you to run asynchronous operations and wait until it is definitely complete before running another operation based on its result. Promises are the backbone of modern asynchronous JavaScript.

+ + + + + + + + + + + + + + + + + +
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
NoNoYesSee Promise.all(), below
+ +

Code example

+ +

The following code fetches an image from the server and displays it inside an {{htmlelement("img")}} element; see it live also, and see also the source code:

+ +
fetch('coffee.jpg')
+.then(response => response.blob())
+.then(myBlob => {
+  let objectURL = URL.createObjectURL(myBlob);
+  let image = document.createElement('img');
+  image.src = objectURL;
+  document.body.appendChild(image);
+})
+.catch(e => {
+  console.log('There has been a problem with your fetch operation: ' + e.message);
+});
+ +

Pitfalls

+ +

Promise chains can be complex and hard to parse. If you nest a number of promises, you can end up with similar troubles to callback hell. For example:

+ +
remotedb.allDocs({
+  include_docs: true,
+  attachments: true
+}).then(function (result) {
+  let docs = result.rows;
+  docs.forEach(function(element) {
+    localdb.put(element.doc).then(function(response) {
+      alert("Pulled doc with id " + element.doc._id + " and added to local db.");
+    }).catch(function (err) {
+      if (err.name == 'conflict') {
+        localdb.get(element.doc._id).then(function (resp) {
+          localdb.remove(resp._id, resp._rev).then(function (resp) {
+// et cetera...
+ +

It is better to use the chaining power of promises to go with a flatter, easier to parse structure:

+ +
remotedb.allDocs(...).then(function (resultOfAllDocs) {
+  return localdb.put(...);
+}).then(function (resultOfPut) {
+  return localdb.get(...);
+}).then(function (resultOfGet) {
+  return localdb.put(...);
+}).catch(function (err) {
+  console.log(err);
+});
+ +

or even:

+ +
remotedb.allDocs(...)
+.then(resultOfAllDocs => {
+  return localdb.put(...);
+})
+.then(resultOfPut => {
+  return localdb.get(...);
+})
+.then(resultOfGet => {
+  return localdb.put(...);
+})
+.catch(err => console.log(err));
+ +

That covers a lot of the basics. For a much more complete treatment, see the excellent We have a problem with promises, by Nolan Lawson.

+ +

Browser compatibility

+ +

{{Compat("javascript.builtins.Promise")}}

+ +

Further information

+ + + +

Promise.all()

+ +

A JavaScript feature that allows you to wait for multiple promises to complete before then running a further operation based on the results of all the other promises.

+ + + + + + + + + + + + + + + + + +
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
NoNoNoYes
+ +

Code example

+ +

The following example fetches several resources from the server, and uses Promise.all() to wait for all of them to be available before then displaying all of them — see it live, and see the source code:

+ +
function fetchAndDecode(url, type) {
+  // Returning the top level promise, so the result of the entire chain is returned out of the function
+  return fetch(url).then(response => {
+    // Depending on what type of file is being fetched, use the relevant function to decode its contents
+    if(type === 'blob') {
+      return response.blob();
+    } else if(type === 'text') {
+      return response.text();
+    }
+  })
+  .catch(e => {
+    console.log(`There has been a problem with your fetch operation for resource "${url}": ` + e.message);
+  });
+}
+
+// Call the fetchAndDecode() method to fetch the images and the text, and store their promises in variables
+let coffee = fetchAndDecode('coffee.jpg', 'blob');
+let tea = fetchAndDecode('tea.jpg', 'blob');
+let description = fetchAndDecode('description.txt', 'text');
+
+// Use Promise.all() to run code only when all three function calls have resolved
+Promise.all([coffee, tea, description]).then(values => {
+  console.log(values);
+  // Store each value returned from the promises in separate variables; create object URLs from the blobs
+  let objectURL1 = URL.createObjectURL(values[0]);
+  let objectURL2 = URL.createObjectURL(values[1]);
+  let descText = values[2];
+
+  // Display the images in <img> elements
+  let image1 = document.createElement('img');
+  let image2 = document.createElement('img');
+  image1.src = objectURL1;
+  image2.src = objectURL2;
+  document.body.appendChild(image1);
+  document.body.appendChild(image2);
+
+  // Display the text in a paragraph
+  let para = document.createElement('p');
+  para.textContent = descText;
+  document.body.appendChild(para);
+});
+ +

Pitfalls

+ + + +

Browser compatibility

+ +

{{Compat("javascript.builtins.Promise.all")}}

+ +

Further information

+ + + +

Async/await

+ +

Syntactic sugar built on top of promises that allows you to run asynchronous operations using syntax that's more like writing synchronous callback code.

+ + + + + + + + + + + + + + + + + +
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
NoNoYesYes (in combination with Promise.all())
+ +

Code example

+ +

The following example is a refactor of the simple promise example we saw earlier that fetches and displays an image, written using async/await (see it live, and see the source code):

+ +
async function myFetch() {
+  let response = await fetch('coffee.jpg');
+  let myBlob = await response.blob();
+
+  let objectURL = URL.createObjectURL(myBlob);
+  let image = document.createElement('img');
+  image.src = objectURL;
+  document.body.appendChild(image);
+}
+
+myFetch();
+ +

Pitfalls

+ + + +

Browser compatibility

+ +

{{Compat("javascript.statements.async_function")}}

+ +

Further information

+ + + +

{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}

+ +

In this module

+ + diff --git a/files/pt-br/learn/javascript/asynchronous/conceitos/index.html b/files/pt-br/learn/javascript/asynchronous/conceitos/index.html deleted file mode 100644 index f2e6759f41..0000000000 --- a/files/pt-br/learn/javascript/asynchronous/conceitos/index.html +++ /dev/null @@ -1,155 +0,0 @@ ---- -title: Conceitos gerais da programação assíncrona -slug: Learn/JavaScript/Asynchronous/Conceitos -translation_of: Learn/JavaScript/Asynchronous/Concepts ---- -
{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}}
- -

Neste artigo, nós vamos ver um número de conceitos importantes relativos à programação assíncrona e como ela se parece em navegadores modernos e em JavaScript. Você deve entender estes conceitos antes de trabalhar com outros artigos neste módulo.

- - - - - - - - - - - - -
Pré-requisitos:Conhecimentos básicos de informática e compreensão dos fundamentos de JavaScript.
Objetivo:Entender os conceitos básicos da programação assíncrona e como ela se manifesta em navegadores e JavaScript.
- -

Assíncrono?

- -

Normalmente, o código de um programa é executado de forma direta, com uma coisa acontecendo por vez. Se uma função depende do resultado de outra função, ela tem que esperar o retorno do resultado, e até que isso aconteça, o programa inteiro praticamente para de funcionar da perspectiva do usuário.

- -

Usuários do Mac, por exemplo, conseguem ver isso como o cursor giratório em arco-íris (ou "beachball", como normalmente é chamado). Este cursor é o jeito do sistema operacional dizer: "o programa atual que você está usando teve que parar e esperar algo terminar de ser executado, e estava demorando tanto que fiquei preocupado se você estava pensando no que aconteceu."

- -

Multi-colored macOS beachball busy spinner

- -

Essa é uma situação frustrante, e não faz bom uso do poder de processamento do computador — especialmente em uma era em que computadores tem múltiplos núcleos de processamento disponíveis. Não há sentido em ficar esperando por algo quando você pode deixar outra tarefa ser executada em um núcleo de processador diferente e deixar que ele te avise quando terminar. Isso te permite fazer mais coisas por enquanto, o que é a base da programação assincrona. Depende do ambiente de programação que você está usando (navegadores da Web, no caso de desenvolvimento da Web) para fornecer APIs que permitem executar essas tarefas de forma assíncrona.

- -

Bloqueio de código

- -

Técnicas async (assíncronas) são muito úteis, principalmente na programação web. Quando um aplicativo web é executado em um navegador e executa um pedaço de código rigoroso sem retornar o controle para o navegador, ele pode parecer que travou. Isso é chamado de blocking; o navegador está bloqueado de continuar a manusear a entrada do usuário e de realizar outras tarefas até que o aplicativo web retorne o controle do processador.

- -

Vamos dar uma olhadinha em alguns exemplos para que você entenda o blocking.

- -

No nosso exemplo simple-sync.html (veja aqui), nós adicionamos um evento de click em um botão para que, quando clicado, ele executa uma tarefa pesada (calcula 10 milhões de datas e depois imprime a última delas no console) e depois adiciona um parágrafo no DOM:

- -
const btn = document.querySelector('button');
-btn.addEventListener('click', () => {
-  let myDate;
-  for(let i = 0; i < 10000000; i++) {
-    let date = new Date();
-    myDate = date
-  }
-
-  console.log(myDate);
-
-  let pElem = document.createElement('p');
-  pElem.textContent = 'This is a newly-added paragraph.';
-  document.body.appendChild(pElem);
-});
- -

Quando o exemplo for executado, abra seu console JavaScript e depois clique no botão  — você verá qua o parágrafo não aparece até que o programa termine de calcular as datas e imprimir a última no console. O código é executado na ordem em que ele aparece na fonte, e a operação seguinte só é executada depois que a primeira for terminada.

- -
-

Nota: O exemplo anterior não é muito realistico. Você nunca calcularia 10 milhões de datas em um aplicativo real! Mas isso serve par te dar um apoio sobre o assunto.

-
- -

No nosso segundo exemplo simple-sync-ui-blocking.html (veja aqui), nós simulamos algo mais realistico que você pode encontrar em uma página real. Nós bloqueamos a interatividade do usuário na renderização da UI. Neste exemplo, nós temos dois botões:

- - - -
function expensiveOperation() {
-  for(let i = 0; i < 1000000; i++) {
-    ctx.fillStyle = 'rgba(0,0,255, 0.2)';
-    ctx.beginPath();
-    ctx.arc(random(0, canvas.width), random(0, canvas.height), 10, degToRad(0), degToRad(360), false);
-    ctx.fill()
-  }
-}
-
-fillBtn.addEventListener('click', expensiveOperation);
-
-alertBtn.addEventListener('click', () =>
-  alert('You clicked me!')
-);
- -

Se você clicar no primeiro botão e imediatamente no segundo, você verá que a mensagem de alerta não aparece até que os círculos sejam totalmente renderizados. A primeira operação bloqueia a segunda até a sua finalização.

- -
-

Nota: OK, no nosso caso, isso é ruim e estamos bloqueando o código de propósito, mas isso é um problema comum que desenvolvedores de aplicativos reais sempre tentam resolver.

-
- -

E por quê isso acontece? A resposta é que o JavaScript é single threaded. E é neste ponto que precisamos introduzir a você o conceito de threads.

- -

Threads

- -

Uma thread é basicamente um único processo que um programa pode usar para concluir tarefas. Cada thread só pode fazer uma tarefa de cada vez:

- -
Tarefa A --> Tarefa B --> Tarefa C
- -

Cada tarefa será executada sequencialmente; uma tarefa tem que ser concluída antes que a próxima possa ser iniciada.

- -

Como foi dito anteriormente, muitos computadores possuem múltiplos núcleos, para que possam fazer múltiplas coisas de uma vez só. Linguagens de programação que podem suportar múltiplas threads podem usar múltiplos processadores para concluir múltiplas tarefas simultâneamente:

- -
Thread 1: Tarefa A --> Tarefa B
-Thread 2: Tarefa C --> Tarefa D
- -

JavaScript é single threaded

- -

JavaScript é tradicionalmente single-threaded. Mesmo com múltiplos núcleos de processamento, você só pode fazê-lo executar tarefas em uma única thread, chamada de main thread (thread principal). Nosso exemplo de cima é executado assim:

- -
Main thread: Renderizar circulos no canvas --> Mostrar alert()
- -

Depois de um tempo, o JavaScript ganhou algumas ferramentas para ajudar em tais problemas. As Web workers te permitem mandar parte do processamento do JavaScript para uma thread separada. Você geralmente usaria uma worker para executar um processo pesado para que a UI não seja bloqueada.

- -
  Main thread: Tarefa A --> Tarefa C
-Worker thread: Tarefa pesada B
- -

Com isso em mente, dê uma olhada em simple-sync-worker.html (veja aqui), com o seu console JavaScript aberto. Isso é uma nova versão do nosso exemplo que calcula 10 milhões de datas em uma tread worker separada. Agora, quando você clica no botão, o navegador é capaz de mostrar o parágrafo antes que as datas sejam terminadas. A primeira opreção não bloqueia a segunda.

- -

Código assíncrono

- -

Web workers podem ser bem úteis, mas elas tem as suas limitações. Uma delas é que elas não são capazes de acessar a {{Glossary("DOM")}} — você não pode fazer com que uma worker faça algo diretamente para atualizar a UI. Nós não poderíamos renderizar nossos 1 milhão de círculos azuis na nossa worker; basicamente ela pode apenas fazer cálculos de números.

- -

O segundo problema é que, mesmo que o código executado em uma worker não cause um bloqueio, ele ainda é um código síncrono. Isso se torna um problema quando uma função depende dos resultados de processos anteriores para funcionar. Considere os diagramas a seguir:

- -
Main thread: Tarefa A --> Tarefa B
- -

Nesse caso, digamos que a tarefa A está fazendo algo como pegar uma imagem do servidor e que a tarefa B faz algo com essa imagem, como colocar um filtro nela. Se você iniciar a tarefa A e depois tentar executar a tarefa B imediatamente, você obterá um erro, porque a imagem não estará disponível ainda.

- -
  Main thread: Tarefa A --> Tarefa B --> |Tarefa D|
-Worker thread: Tarefa C ---------------> |      |
- -

Neste caso, digamos que a tarefa D faz uso dos resultados das tarefas B e C. Se nós pudermos garantir que esses resultados estejam disponíveis ao mesmo tempo, então tudo talvez esteja bem, mas isso não é garantido. Se a tarefa D tentar ser executada quando um dos resultados não estiver disponível, ela retornará um erro.

- -

Para consertarmos tais problemas, os browsers nos permitem executar certas operações de modo assíncrono. Recursos como Promises te permitem executar uma operação e depois esperar pelo resultado antes de executar outra operação: 

- -
Main thread: Tarefa A                   Tarefa B
-    Promise:       |___operação async___|
- -

Já que a operação está acontecendo em outro lugar, a main thread não está bloqueada enquanto a operação assíncrona está sendo processada.

- -

Nós vamos começar a olhar em como podemos escrever código assíncrono no próximo artigo.

- -

Conclusão

- -

O design moderno de software gira em torno do uso de programação assíncrona, para permitir que os programas façam mais de uma coisa por vez. Ao usar APIs mais novas e mais poderosas, você encontrará mais casos em que a única maneira de fazer as coisas é assincronamente. Costumava ser difícil escrever código assíncrono. Ainda é preciso se acostumar, mas ficou muito mais fácil. No restante deste módulo, exploraremos ainda mais por que o código assíncrono é importante e como projetar o código que evita alguns dos problemas descritos acima.

- -

Nesse módulo

- - diff --git a/files/pt-br/learn/javascript/asynchronous/concepts/index.html b/files/pt-br/learn/javascript/asynchronous/concepts/index.html new file mode 100644 index 0000000000..f2e6759f41 --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/concepts/index.html @@ -0,0 +1,155 @@ +--- +title: Conceitos gerais da programação assíncrona +slug: Learn/JavaScript/Asynchronous/Conceitos +translation_of: Learn/JavaScript/Asynchronous/Concepts +--- +
{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}}
+ +

Neste artigo, nós vamos ver um número de conceitos importantes relativos à programação assíncrona e como ela se parece em navegadores modernos e em JavaScript. Você deve entender estes conceitos antes de trabalhar com outros artigos neste módulo.

+ + + + + + + + + + + + +
Pré-requisitos:Conhecimentos básicos de informática e compreensão dos fundamentos de JavaScript.
Objetivo:Entender os conceitos básicos da programação assíncrona e como ela se manifesta em navegadores e JavaScript.
+ +

Assíncrono?

+ +

Normalmente, o código de um programa é executado de forma direta, com uma coisa acontecendo por vez. Se uma função depende do resultado de outra função, ela tem que esperar o retorno do resultado, e até que isso aconteça, o programa inteiro praticamente para de funcionar da perspectiva do usuário.

+ +

Usuários do Mac, por exemplo, conseguem ver isso como o cursor giratório em arco-íris (ou "beachball", como normalmente é chamado). Este cursor é o jeito do sistema operacional dizer: "o programa atual que você está usando teve que parar e esperar algo terminar de ser executado, e estava demorando tanto que fiquei preocupado se você estava pensando no que aconteceu."

+ +

Multi-colored macOS beachball busy spinner

+ +

Essa é uma situação frustrante, e não faz bom uso do poder de processamento do computador — especialmente em uma era em que computadores tem múltiplos núcleos de processamento disponíveis. Não há sentido em ficar esperando por algo quando você pode deixar outra tarefa ser executada em um núcleo de processador diferente e deixar que ele te avise quando terminar. Isso te permite fazer mais coisas por enquanto, o que é a base da programação assincrona. Depende do ambiente de programação que você está usando (navegadores da Web, no caso de desenvolvimento da Web) para fornecer APIs que permitem executar essas tarefas de forma assíncrona.

+ +

Bloqueio de código

+ +

Técnicas async (assíncronas) são muito úteis, principalmente na programação web. Quando um aplicativo web é executado em um navegador e executa um pedaço de código rigoroso sem retornar o controle para o navegador, ele pode parecer que travou. Isso é chamado de blocking; o navegador está bloqueado de continuar a manusear a entrada do usuário e de realizar outras tarefas até que o aplicativo web retorne o controle do processador.

+ +

Vamos dar uma olhadinha em alguns exemplos para que você entenda o blocking.

+ +

No nosso exemplo simple-sync.html (veja aqui), nós adicionamos um evento de click em um botão para que, quando clicado, ele executa uma tarefa pesada (calcula 10 milhões de datas e depois imprime a última delas no console) e depois adiciona um parágrafo no DOM:

+ +
const btn = document.querySelector('button');
+btn.addEventListener('click', () => {
+  let myDate;
+  for(let i = 0; i < 10000000; i++) {
+    let date = new Date();
+    myDate = date
+  }
+
+  console.log(myDate);
+
+  let pElem = document.createElement('p');
+  pElem.textContent = 'This is a newly-added paragraph.';
+  document.body.appendChild(pElem);
+});
+ +

Quando o exemplo for executado, abra seu console JavaScript e depois clique no botão  — você verá qua o parágrafo não aparece até que o programa termine de calcular as datas e imprimir a última no console. O código é executado na ordem em que ele aparece na fonte, e a operação seguinte só é executada depois que a primeira for terminada.

+ +
+

Nota: O exemplo anterior não é muito realistico. Você nunca calcularia 10 milhões de datas em um aplicativo real! Mas isso serve par te dar um apoio sobre o assunto.

+
+ +

No nosso segundo exemplo simple-sync-ui-blocking.html (veja aqui), nós simulamos algo mais realistico que você pode encontrar em uma página real. Nós bloqueamos a interatividade do usuário na renderização da UI. Neste exemplo, nós temos dois botões:

+ + + +
function expensiveOperation() {
+  for(let i = 0; i < 1000000; i++) {
+    ctx.fillStyle = 'rgba(0,0,255, 0.2)';
+    ctx.beginPath();
+    ctx.arc(random(0, canvas.width), random(0, canvas.height), 10, degToRad(0), degToRad(360), false);
+    ctx.fill()
+  }
+}
+
+fillBtn.addEventListener('click', expensiveOperation);
+
+alertBtn.addEventListener('click', () =>
+  alert('You clicked me!')
+);
+ +

Se você clicar no primeiro botão e imediatamente no segundo, você verá que a mensagem de alerta não aparece até que os círculos sejam totalmente renderizados. A primeira operação bloqueia a segunda até a sua finalização.

+ +
+

Nota: OK, no nosso caso, isso é ruim e estamos bloqueando o código de propósito, mas isso é um problema comum que desenvolvedores de aplicativos reais sempre tentam resolver.

+
+ +

E por quê isso acontece? A resposta é que o JavaScript é single threaded. E é neste ponto que precisamos introduzir a você o conceito de threads.

+ +

Threads

+ +

Uma thread é basicamente um único processo que um programa pode usar para concluir tarefas. Cada thread só pode fazer uma tarefa de cada vez:

+ +
Tarefa A --> Tarefa B --> Tarefa C
+ +

Cada tarefa será executada sequencialmente; uma tarefa tem que ser concluída antes que a próxima possa ser iniciada.

+ +

Como foi dito anteriormente, muitos computadores possuem múltiplos núcleos, para que possam fazer múltiplas coisas de uma vez só. Linguagens de programação que podem suportar múltiplas threads podem usar múltiplos processadores para concluir múltiplas tarefas simultâneamente:

+ +
Thread 1: Tarefa A --> Tarefa B
+Thread 2: Tarefa C --> Tarefa D
+ +

JavaScript é single threaded

+ +

JavaScript é tradicionalmente single-threaded. Mesmo com múltiplos núcleos de processamento, você só pode fazê-lo executar tarefas em uma única thread, chamada de main thread (thread principal). Nosso exemplo de cima é executado assim:

+ +
Main thread: Renderizar circulos no canvas --> Mostrar alert()
+ +

Depois de um tempo, o JavaScript ganhou algumas ferramentas para ajudar em tais problemas. As Web workers te permitem mandar parte do processamento do JavaScript para uma thread separada. Você geralmente usaria uma worker para executar um processo pesado para que a UI não seja bloqueada.

+ +
  Main thread: Tarefa A --> Tarefa C
+Worker thread: Tarefa pesada B
+ +

Com isso em mente, dê uma olhada em simple-sync-worker.html (veja aqui), com o seu console JavaScript aberto. Isso é uma nova versão do nosso exemplo que calcula 10 milhões de datas em uma tread worker separada. Agora, quando você clica no botão, o navegador é capaz de mostrar o parágrafo antes que as datas sejam terminadas. A primeira opreção não bloqueia a segunda.

+ +

Código assíncrono

+ +

Web workers podem ser bem úteis, mas elas tem as suas limitações. Uma delas é que elas não são capazes de acessar a {{Glossary("DOM")}} — você não pode fazer com que uma worker faça algo diretamente para atualizar a UI. Nós não poderíamos renderizar nossos 1 milhão de círculos azuis na nossa worker; basicamente ela pode apenas fazer cálculos de números.

+ +

O segundo problema é que, mesmo que o código executado em uma worker não cause um bloqueio, ele ainda é um código síncrono. Isso se torna um problema quando uma função depende dos resultados de processos anteriores para funcionar. Considere os diagramas a seguir:

+ +
Main thread: Tarefa A --> Tarefa B
+ +

Nesse caso, digamos que a tarefa A está fazendo algo como pegar uma imagem do servidor e que a tarefa B faz algo com essa imagem, como colocar um filtro nela. Se você iniciar a tarefa A e depois tentar executar a tarefa B imediatamente, você obterá um erro, porque a imagem não estará disponível ainda.

+ +
  Main thread: Tarefa A --> Tarefa B --> |Tarefa D|
+Worker thread: Tarefa C ---------------> |      |
+ +

Neste caso, digamos que a tarefa D faz uso dos resultados das tarefas B e C. Se nós pudermos garantir que esses resultados estejam disponíveis ao mesmo tempo, então tudo talvez esteja bem, mas isso não é garantido. Se a tarefa D tentar ser executada quando um dos resultados não estiver disponível, ela retornará um erro.

+ +

Para consertarmos tais problemas, os browsers nos permitem executar certas operações de modo assíncrono. Recursos como Promises te permitem executar uma operação e depois esperar pelo resultado antes de executar outra operação: 

+ +
Main thread: Tarefa A                   Tarefa B
+    Promise:       |___operação async___|
+ +

Já que a operação está acontecendo em outro lugar, a main thread não está bloqueada enquanto a operação assíncrona está sendo processada.

+ +

Nós vamos começar a olhar em como podemos escrever código assíncrono no próximo artigo.

+ +

Conclusão

+ +

O design moderno de software gira em torno do uso de programação assíncrona, para permitir que os programas façam mais de uma coisa por vez. Ao usar APIs mais novas e mais poderosas, você encontrará mais casos em que a única maneira de fazer as coisas é assincronamente. Costumava ser difícil escrever código assíncrono. Ainda é preciso se acostumar, mas ficou muito mais fácil. No restante deste módulo, exploraremos ainda mais por que o código assíncrono é importante e como projetar o código que evita alguns dos problemas descritos acima.

+ +

Nesse módulo

+ + diff --git a/files/pt-br/learn/javascript/asynchronous/escolhendo_abordagem_correta/index.html b/files/pt-br/learn/javascript/asynchronous/escolhendo_abordagem_correta/index.html deleted file mode 100644 index 254bc41a99..0000000000 --- a/files/pt-br/learn/javascript/asynchronous/escolhendo_abordagem_correta/index.html +++ /dev/null @@ -1,523 +0,0 @@ ---- -title: Escolhendo a abordagem correta -slug: Learn/JavaScript/Asynchronous/Escolhendo_abordagem_correta -translation_of: Learn/JavaScript/Asynchronous/Choosing_the_right_approach ---- -
{{LearnSidebar}}
- -
{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}
- -

To finish this module off, we'll provide a brief discussion of the different coding techniques and features we've discussed throughout, looking at which one you should use when, with recommendations and reminders of common pitfalls where appropriate. We'll probably add to this resource as time goes on.

- - - - - - - - - - - - -
Prerequisites:Basic computer literacy, a reasonable understanding of JavaScript fundamentals.
Objective:To be able to make a sound choice of when to use different asynchronous programming techniques.
- -

Asynchronous callbacks

- -

Generally found in old-style APIs, involves a function being passed into another function as a parameter, which is then invoked when an asynchronous operation has been completed, so that the callback can in turn do something with the result. This is the precursor to promises; it's not as efficient or flexible. Use only when necessary.

- - - - - - - - - - - - - - - - - - - -
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
NoYes (recursive callbacks)Yes (nested callbacks)No
- -

Code example

- -

An example that loads a resource via the XMLHttpRequest API (run it live, and see the source):

- -
function loadAsset(url, type, callback) {
-  let xhr = new XMLHttpRequest();
-  xhr.open('GET', url);
-  xhr.responseType = type;
-
-  xhr.onload = function() {
-    callback(xhr.response);
-  };
-
-  xhr.send();
-}
-
-function displayImage(blob) {
-  let objectURL = URL.createObjectURL(blob);
-
-  let image = document.createElement('img');
-  image.src = objectURL;
-  document.body.appendChild(image);
-}
-
-loadAsset('coffee.jpg', 'blob', displayImage);
- -

Pitfalls

- - - -

Browser compatibility

- -

Really good general support, although the exact support for callbacks in APIs depends on the particular API. Refer to the reference documentation for the API you're using for more specific support info.

- -

Further information

- - - -

setTimeout()

- -

setTimeout() is a method that allows you to run a function after an arbitrary amount of time has passed.

- - - - - - - - - - - - - - - - - -
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
YesYes (recursive timeouts)Yes (nested timeouts)No
- -

Code example

- -

Here the browser will wait two seconds before executing the anonymous function, then will display the alert message (see it running live, and see the source code):

- -
let myGreeting = setTimeout(function() {
-  alert('Hello, Mr. Universe!');
-}, 2000)
- -

Pitfalls

- -

You can use recursive setTimeout() calls to run a function repeatedly in a similar fashion to setInterval(), using code like this:

- -
let i = 1;
-setTimeout(function run() {
-  console.log(i);
-  i++;
-
-  setTimeout(run, 100);
-}, 100);
- -

There is a difference between recursive setTimeout() and setInterval():

- - - -

When your code has the potential to take longer to run than the time interval you’ve assigned, it’s better to use recursive setTimeout() — this will keep the time interval constant between executions regardless of how long the code takes to execute, and you won't get errors.

- -

Browser compatibility

- -

{{Compat("api.WindowOrWorkerGlobalScope.setTimeout")}}

- -

Further information

- - - -

setInterval()

- -

setInterval() is a method that allows you to run a function repeatedly with a set interval of time between each execution. Not as efficient as requestAnimationFrame(), but allows you to choose a running rate/frame rate.

- - - - - - - - - - - - - - - - - -
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
NoYesNo (unless it is the same one)No
- -

Code example

- -

The following function creates a new Date() object, extracts a time string out of it using toLocaleTimeString(), and then displays it in the UI. We then run it once per second using setInterval(), creating the effect of a digital clock that updates once per second (see this live, and also see the source):

- -
function displayTime() {
-   let date = new Date();
-   let time = date.toLocaleTimeString();
-   document.getElementById('demo').textContent = time;
-}
-
-const createClock = setInterval(displayTime, 1000);
- -

Pitfalls

- - - -

Browser compatibility

- -

{{Compat("api.WindowOrWorkerGlobalScope.setInterval")}}

- -

Further information

- - - -

requestAnimationFrame()

- -

requestAnimationFrame() is a method that allows you to run a function repeatedly, and efficiently, at the best framerate available given the current browser/system. You should, if at all possible, use this instead of setInterval()/recursive setTimeout(), unless you need a specific framerate.

- - - - - - - - - - - - - - - - - -
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
NoYesNo (unless it is the same one)No
- -

Code example

- -

A simple animated spinner; you can find this example live on GitHub (see the source code also):

- -
const spinner = document.querySelector('div');
-let rotateCount = 0;
-let startTime = null;
-let rAF;
-
-function draw(timestamp) {
-    if(!startTime) {
-        startTime = timestamp;
-    }
-
-    rotateCount = (timestamp - startTime) / 3;
-
-    if(rotateCount > 359) {
-        rotateCount %= 360;
-    }
-
-    spinner.style.transform = 'rotate(' + rotateCount + 'deg)';
-
-    rAF = requestAnimationFrame(draw);
-}
-
-draw();
- -

Pitfalls

- - - -

Browser compatibility

- -

{{Compat("api.Window.requestAnimationFrame")}}

- -

Further information

- - - -

Promises

- -

Promises are a JavaScript feature that allows you to run asynchronous operations and wait until it is definitely complete before running another operation based on its result. Promises are the backbone of modern asynchronous JavaScript.

- - - - - - - - - - - - - - - - - -
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
NoNoYesSee Promise.all(), below
- -

Code example

- -

The following code fetches an image from the server and displays it inside an {{htmlelement("img")}} element; see it live also, and see also the source code:

- -
fetch('coffee.jpg')
-.then(response => response.blob())
-.then(myBlob => {
-  let objectURL = URL.createObjectURL(myBlob);
-  let image = document.createElement('img');
-  image.src = objectURL;
-  document.body.appendChild(image);
-})
-.catch(e => {
-  console.log('There has been a problem with your fetch operation: ' + e.message);
-});
- -

Pitfalls

- -

Promise chains can be complex and hard to parse. If you nest a number of promises, you can end up with similar troubles to callback hell. For example:

- -
remotedb.allDocs({
-  include_docs: true,
-  attachments: true
-}).then(function (result) {
-  let docs = result.rows;
-  docs.forEach(function(element) {
-    localdb.put(element.doc).then(function(response) {
-      alert("Pulled doc with id " + element.doc._id + " and added to local db.");
-    }).catch(function (err) {
-      if (err.name == 'conflict') {
-        localdb.get(element.doc._id).then(function (resp) {
-          localdb.remove(resp._id, resp._rev).then(function (resp) {
-// et cetera...
- -

It is better to use the chaining power of promises to go with a flatter, easier to parse structure:

- -
remotedb.allDocs(...).then(function (resultOfAllDocs) {
-  return localdb.put(...);
-}).then(function (resultOfPut) {
-  return localdb.get(...);
-}).then(function (resultOfGet) {
-  return localdb.put(...);
-}).catch(function (err) {
-  console.log(err);
-});
- -

or even:

- -
remotedb.allDocs(...)
-.then(resultOfAllDocs => {
-  return localdb.put(...);
-})
-.then(resultOfPut => {
-  return localdb.get(...);
-})
-.then(resultOfGet => {
-  return localdb.put(...);
-})
-.catch(err => console.log(err));
- -

That covers a lot of the basics. For a much more complete treatment, see the excellent We have a problem with promises, by Nolan Lawson.

- -

Browser compatibility

- -

{{Compat("javascript.builtins.Promise")}}

- -

Further information

- - - -

Promise.all()

- -

A JavaScript feature that allows you to wait for multiple promises to complete before then running a further operation based on the results of all the other promises.

- - - - - - - - - - - - - - - - - -
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
NoNoNoYes
- -

Code example

- -

The following example fetches several resources from the server, and uses Promise.all() to wait for all of them to be available before then displaying all of them — see it live, and see the source code:

- -
function fetchAndDecode(url, type) {
-  // Returning the top level promise, so the result of the entire chain is returned out of the function
-  return fetch(url).then(response => {
-    // Depending on what type of file is being fetched, use the relevant function to decode its contents
-    if(type === 'blob') {
-      return response.blob();
-    } else if(type === 'text') {
-      return response.text();
-    }
-  })
-  .catch(e => {
-    console.log(`There has been a problem with your fetch operation for resource "${url}": ` + e.message);
-  });
-}
-
-// Call the fetchAndDecode() method to fetch the images and the text, and store their promises in variables
-let coffee = fetchAndDecode('coffee.jpg', 'blob');
-let tea = fetchAndDecode('tea.jpg', 'blob');
-let description = fetchAndDecode('description.txt', 'text');
-
-// Use Promise.all() to run code only when all three function calls have resolved
-Promise.all([coffee, tea, description]).then(values => {
-  console.log(values);
-  // Store each value returned from the promises in separate variables; create object URLs from the blobs
-  let objectURL1 = URL.createObjectURL(values[0]);
-  let objectURL2 = URL.createObjectURL(values[1]);
-  let descText = values[2];
-
-  // Display the images in <img> elements
-  let image1 = document.createElement('img');
-  let image2 = document.createElement('img');
-  image1.src = objectURL1;
-  image2.src = objectURL2;
-  document.body.appendChild(image1);
-  document.body.appendChild(image2);
-
-  // Display the text in a paragraph
-  let para = document.createElement('p');
-  para.textContent = descText;
-  document.body.appendChild(para);
-});
- -

Pitfalls

- - - -

Browser compatibility

- -

{{Compat("javascript.builtins.Promise.all")}}

- -

Further information

- - - -

Async/await

- -

Syntactic sugar built on top of promises that allows you to run asynchronous operations using syntax that's more like writing synchronous callback code.

- - - - - - - - - - - - - - - - - -
Useful for...
Single delayed operationRepeating operationMultiple sequential operationsMultiple simultaneous operations
NoNoYesYes (in combination with Promise.all())
- -

Code example

- -

The following example is a refactor of the simple promise example we saw earlier that fetches and displays an image, written using async/await (see it live, and see the source code):

- -
async function myFetch() {
-  let response = await fetch('coffee.jpg');
-  let myBlob = await response.blob();
-
-  let objectURL = URL.createObjectURL(myBlob);
-  let image = document.createElement('img');
-  image.src = objectURL;
-  document.body.appendChild(image);
-}
-
-myFetch();
- -

Pitfalls

- - - -

Browser compatibility

- -

{{Compat("javascript.statements.async_function")}}

- -

Further information

- - - -

{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}

- -

In this module

- - diff --git a/files/pt-br/learn/javascript/asynchronous/introducing/index.html b/files/pt-br/learn/javascript/asynchronous/introducing/index.html new file mode 100644 index 0000000000..b95a88d35c --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/introducing/index.html @@ -0,0 +1,283 @@ +--- +title: Introdução ao JavaScript Async +slug: Learn/JavaScript/Asynchronous/Introdução +translation_of: Learn/JavaScript/Asynchronous/Introducing +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}
+ +
Neste artigo nós recapitulamos brevemente os problemas que são associados com o JavaScript síncrono, e dar  uma primeira olhada em algumas das diferentes técnicas assíncronas que você vai encontrar, mostrando como elas podem nos ajudar a resolver tais problemas.
+ +
+ + + + + + + + + + + + +
Pré-requisitos:Conhecimentos básicos de informática e sobre os fundamentos do JavaScript.
Objetivo:Ganhar familiaridade com o que é o Js assíncrono e como ele se difere do Js síncrono.
+ +

JavaScript síncrono

+ +

Para entendermos o que é o {{Glossary("asynchronous")}} JavaScript, nós primeiro temos que ter certeza que entedemos o que é o {{Glossary("synchronous")}} JavaScript. Essa seção revê um pouco das informações que nós vimos no artigo anterior.

+ +

Muitas das funcionalidades que nós vimos em áreas anteriores são síncronas — você executa um código, e o reultado é retornado assim que o navegador puder. Vamos ver um exemplo simples (veja aqui, e veja o código fonte):

+ +
const btn = document.querySelector('button');
+btn.addEventListener('click', () => {
+  alert('Você clicou em mim!');
+
+  let pElem = document.createElement('p');
+  pElem.textContent = 'Este é um novo parágrafo adicionado';
+  document.body.appendChild(pElem);
+});
+
+ +

Neste bloco, as linhas são executadas uma após a outra:

+ +
    +
  1. Nós damos referência à um elemento {{htmlelement("button")}} que já está disponível na DOM.
  2. +
  3. Nós adicionamos um evento de click, e quando ele for clicado ele fará o seguinte: +
      +
    1. Mostrar uma mensagem no alert().
    2. +
    3. Uma vez que o alert for dispensado, nós criamos um elemento {{htmlelement("p")}}.
    4. +
    5. Depois nós o preenchemos com um texto.
    6. +
    7. E finalmente, o adicionamos no body.
    8. +
    +
  4. +
+ +

Enquanro cada operação é processada, nada mais pode acontecer — a renderização é pausada. Isso acontece porque o JavaScript opera em uma única thread (JavaScript é single threaded). Apenas uma coisa pode acontecer por vez, em uma única thread principal, e tudo é bloqueado até que a operação seja concluída.

+ +

Então, no exemplo acima, depois que você tenha clicado no botão, o parágrafo não vai aparecer até que o botão OK do alert seja pressionado. Tente isso com o botão a seguir:

+ + + +

{{EmbedLiveSample('Synchronous_JavaScript', '100%', '70px')}}

+ +
+

Nota: É importante lembrar que, mesmo sendo muito útil para demonstar uma situação de blocking, o alert() não é de bom uso em aplicativos reais.

+
+ +

Asynchronous JavaScript

+ +

Por razões esclarecidas anteriormente (e.g. relativas ao blocking), muitas funcionalidades de APIs da Web agora usam código assíncrono na execução, especialmente aquelas que acessam ou buscam algum tipo de recurso de um dispositivo externo, como pegar um arquivo da rede, acessar um banco de dados e retornar dados dele, acessar uma stream de uma web cam, ou transmitir uma tela para um dispositivo VR.

+ +

Por que é tão difícil trabalhar com isso usando códigos síncronos? Vamos dar uma olhada em um exemplo rápido. Quando você pega uma imagem de um servidor, você não pode retornar o resultado imediatamente. Isso significa que o pseudocódigo a seguir não poderia funcionar:

+ +
let resposta = fetch('myImage.png');
+let blob = resposta.blob();
+// Mostra sua imagem na UI
+ +

Isso acontece por que você não sabe quanto tempo a imagem levará para ser baixada, então quando você executar a segunda linha, ela vai resultar em um erro (provalvelmente sempre) porque a  resposta não estará disponível ainda. Você precisa que o seu código espere até que a resposta seja retornada antes de fazer algo com ela.

+ +

Existem dois tipos principais de estilo de código assíncrono que você encontrará no código JavaScript, as callbacks com um estilo old-school e código em um estilo das promises mais recente. Nas seções abaixo, revisaremos cada um deles por vez.

+ +

Callbacks assíncronas

+ +

Callback são funções que são passada como parâmetros na chamada de outra função que vai executar código por trás do panos. Quando esse código por trás dos panos terminar de ser executado, a função callback será chamada para te informar que a tarefa foi finalizada ou que algo do seu interesse aconteceu. O uso das callbacks é um pouco antiquado agora, mas você ainda pode vê-las em um número de APIs comumente usadas.

+ +

Um exemplo de uma callback async é o segundo parâmetro do método {{domxref("EventTarget.addEventListener", "addEventListener()")}} (como vimos em ação anteriormente):

+ +
btn.addEventListener('click', () => {
+  alert('Você clicou em mim!');
+
+  let pElem = document.createElement('p');
+  pElem.textContent = 'Este é um novo parágrafo.';
+  document.body.appendChild(pElem);
+});
+ +

O primeiro parâmetro é o tipo de evento a ser executado e o segundo parâmetro é uma função callback que é chamada quando o evento é disparado.

+ +

Quando passamos uma função callback como um parâmetro em outra função, nós apenas estamos passando a rêferencia da função como argumento, ou seja, a função callback não é executada imediatamente. Ela é chamada de volta assíncronamente dentro do corpo da função que a contém, que é responsável por executar a função callback quando for necessário.

+ +

Você pode escrever a sua própria função que contém uma callback facilmente. Vamos dar uma olhada em outro exemplo que carrega uma arquivo usando a API XMLHttpRequest (veja aqui, and veja o código fonte):

+ +
function loadAsset(url, type, callback) {
+  let xhr = new XMLHttpRequest();
+  xhr.open('GET', url);
+  xhr.responseType = type;
+
+  xhr.onload = function() {
+    callback(xhr.response);
+  };
+
+  xhr.send();
+}
+
+function displayImage(blob) {
+  let objectURL = URL.createObjectURL(blob);
+
+  let image = document.createElement('img');
+  image.src = objectURL;
+  document.body.appendChild(image);
+}
+
+loadAsset('coffee.jpg', 'blob', displayImage);
+ +

Aqui nós criamos uma função displayImage() que simplesmente representa um blob que foi passada à ela como uma URL de objeto, e depois cria uma imagem para mostrar a URL, adicionando-a ao <body> do documento. Entretando, nós criamos depois uma função loadAsset() que pega uma callback como parâmetro, junto com uma URL a ser buscada e um tipo para o conteúdo. Ela usa o XMLHttpRequest (abreviação: "XHR") para buscar o recurso na URL dada, para depois passar a resposta para a callback para fazer algo com isso. Neste caso a callback está esperando o XHR  terminar de baixar o recurso (usando o manipulador de eventos onload) antes de passá-lo para a callback.

+ +

Callback são versáteis — elas não apenas lhe permitem controlar a ordem em que as funções são executadas e quais dados são passados entre elas, elas também podem passar dados para diferentes funçoes dependendo das circunstâncias. Então você pode ter ações diferentes para executar na resposta baixada, como processJSON(), displayText(), etc.

+ +

Note que nem todas as callback são assíncronas — algumas são executadas de um modo síncrono. Um exemplo é quando nós usamos o método {{jsxref("Array.prototype.forEach()")}} para iterar sobre os itens de uma array (veja aqui, e a fonte):

+ +
const gods = ['Apollo', 'Artemis', 'Ares', 'Zeus'];
+
+gods.forEach(function (eachName, index){
+  console.log(index + '. ' + eachName);
+});
+ +

Neste exemplo nós iteramos sobra uma array de Deuses Gregos e imprimos o índice e seus valores no console. O parâmetro de forEach() é uma callback function, que por si só toma dois parâmetros: uma refêrencia ao nome da array e e os valores dos índices. Entretanto, ela não espera por algo para fazer a execução, pois isso acontece imediatamente

+ +

Promises

+ +

Promises são uma nova maneira de escrever código assíncrono que você verá em APIs Web modernas. Um bom exemplo disso é a API fetch(), que é basicamente uma versão mais moderna e eficiente de {{domxref("XMLHttpRequest")}}. Vamos dar uma olhada em um exemplo rápido, do nosso artigo de Pegando dados do servidor:

+ +
fetch('products.json').then(function(response) {
+  return response.json();
+}).then(function(json) {
+  products = json;
+  initialize();
+}).catch(function(err) {
+  console.log('Fetch problem: ' + err.message);
+});
+ +
+

Nota: Você pode encontrar a versão finalizada no GitHub (veja aqui, e também seja a execução).

+
+ +

Aqui nós vemos fetch() pegando um único parâmetro — a URL de um recurso que você quer pegar da rede — e retornando uma promise. A promise é um objeto que representa a conclusão ou falha da operação assíncrona. Ela represente um estado intermediário, por assim dizer. É praticamente o jetio do navegador de dizer "Eu prometo voltar para você com a resposta o mais rápido possível", daí o nome "promessa".

+ +

Você pode levar um tempo para se acostumar com esse conceito; Ele se parece um pouco com o {{interwiki("wikipedia", "Gato de Schrödinger")}} em ação. Nenhum dos possíveis resultados aconteceu ainda, então a operação fetch está esperando pelo resultado do navegador que vai completar a operação em algum ponto no futuro.

+ +

Nós temos três blocos de código encadeados ao fim do fetch():

+ + + +
+

Nota: Você vai aprender mais sobre promises mais tarde no módulo, então não se preocupe se você não entendeu muito bem.

+
+ +

A fila de eventos

+ +

Operações assíncronas como as promises são colocadas em uma fila de eventos, que é executada depois que a main thread terminar de ser processada. As operações serão completadas assim que for possível e depois retornam seus resultados para o ambiente JavaScript.

+ +

Promises versus callbacks

+ +

As promises tem algumas semelhanças com as callbacks. Elas são basicamente um objeto retornado em que você vincula funções callback, ao invés de passar as callbacks para uma função.

+ +

Entretanto, as promises são feitas especificamente para lidarmos com operações async, e ter muitas vantagens sobre as velhas callbacks:

+ + + +

A natureza do código assíncrono

+ +

Vamos explorar um exemplo que ilustra a natureza do código assíncrono, mostrando o que pode acontecer quando nós não estamos cientes da ordem de execução e dos problemas em tentar tratar código async como código síncrono. O exemplo a seguir é muito similar ao que vimos antes (veja aqui, e a fonte). Uma diferença e que nós icluimos um número de declarações {{domxref("console.log()")}} para ilustrar na ordem que você pensa que o código fosse executado.

+ +
console.log ('Starting');
+let image;
+
+fetch('coffee.jpg').then((response) => {
+  console.log('It worked :)')
+  return response.blob();
+}).then((myBlob) => {
+  let objectURL = URL.createObjectURL(myBlob);
+  image = document.createElement('img');
+  image.src = objectURL;
+  document.body.appendChild(image);
+}).catch((error) => {
+  console.log('There has been a problem with your fetch operation: ' + error.message);
+});
+
+console.log ('All done!');
+ +

O navegador vai começar a executar o código, veja a primeira declaração console.log()(Starting) e a execute, e depois crie a variável image.

+ +

Depois a segunda linha vai começar a ser executada começando com o bloco fetch(), mas desde que fetch() é executado assíncronamente sem bloquear nada, a execução do código continua mesmo depois do código promise, alcançando a última declaração console.log()(All done!) e imprimindo a no console.

+ +

Uma vez que o bloco fetch() tenha terminado a sua execução e retornado seu resultado com os blocos .then(), nós finalmente veremos a segunda mensagem console.log() (It worked :)) appear. Então as mensagens aparecem nessa ordem:

+ + + +

Se isso te deixa confuso, então considere o exemplo a seguir:

+ +
console.log("registering click handler");
+
+button.addEventListener('click', () => {
+  console.log("get click");
+});
+
+console.log("all done");
+ +

Isso é bem similar no comportamento — a primeira e a terceira mensagens console.log() são mostradas imediatamente, mas a segunda está bloqueada até alguém clique no botão. O exemplo anterior funciona da mesma forma, exceto que no caso a segunda mensagem está bloqueada na promise pegando um recurso e depois o mostra na tela.

+ +

Em um exemplo mais superficial, esse tipo de configuração poderia causar um problema — você não pode incluir um bloco async que retorna um resultado, que depois depende de um código síncrono. Você não pode garantir que a função async vai retornar antes que o navegador processou o bloco síncrono.

+ +

Para ver isso em ação, tente fazer uma cópia local do nosso exemplo, e mudar o terceiro console.log() para o seguinte:

+ +
console.log ('Tudo Feito! ' + image.src + 'mostrada.');
+ +

Agora você deve ter um erro no seu console ao invés da terceira mensagem:

+ +
TypeError: image is undefined; can't access its "src" property
+ +

Isso acontece porque o navegador tenta executar o terceiro console.log() e o bloco fetch() não terminou de ser executado e não foi dado  um valor para a variável image.

+ +
+

Nota:Por razões de segurança, você não pode usar o fetch()  com arquivos do seu sistema local (ou executar operações localmente); para executar o exemplo acima você teria que rodá-lo em um servidor local.

+
+ +

Aprendizado ativo: faça tudo async!

+ +

Faça que o exemplo problemático de fetch() imprima três mensagens console.log() na tela na ordem desejada, você pode fazer a útima declaração console.log() assíncrona também. Isso pode ser feito colocando ela em outro bloco .then() encadeamo no final do segundo bloco, ou por simplesmente movê-lo para dentro do segundo bloco then().

+ +
+

Note: If you get stuck, you can find an answer here (see it running live also). You can also find a lot more information on promises in our Graceful asynchronous programming with Promises guide, later on in the module.

+
+ +

Conclusion

+ +

In its most basic form, JavaScript is a synchronous, blocking, single-threaded language, in which only one operation can be in progress at a time. But web browsers define functions and APIs that allow us to register functions that should not be executed synchronously, and should instead be invoked asynchronously when some kind of event occurs (the passage of time, the user's interaction with the mouse, or the arrival of data over the network, for example). This means that you can let your code do several things at the same time without stopping or blocking your main thread.

+ +

Whether we want to run code synchronously or asynchronously will depend on what we're trying to do.

+ +

There are times when we want things to load and happen right away. For example when applying some user-defined styles to a webpage you'll want the styles to be applied as soon as possible.

+ +

If we're running an operation that takes time however, like querying a database and using the results to populate templates, it is better to push this off the main thread and complete the task asynchronously. Over time, you'll learn when it makes more sense to choose an asynchronous technique over a synchronous one.

+ + + +

{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}

+ +

In this module

+ + diff --git "a/files/pt-br/learn/javascript/asynchronous/introdu\303\247\303\243o/index.html" "b/files/pt-br/learn/javascript/asynchronous/introdu\303\247\303\243o/index.html" deleted file mode 100644 index b95a88d35c..0000000000 --- "a/files/pt-br/learn/javascript/asynchronous/introdu\303\247\303\243o/index.html" +++ /dev/null @@ -1,283 +0,0 @@ ---- -title: Introdução ao JavaScript Async -slug: Learn/JavaScript/Asynchronous/Introdução -translation_of: Learn/JavaScript/Asynchronous/Introducing ---- -
{{LearnSidebar}}
- -
{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}
- -
Neste artigo nós recapitulamos brevemente os problemas que são associados com o JavaScript síncrono, e dar  uma primeira olhada em algumas das diferentes técnicas assíncronas que você vai encontrar, mostrando como elas podem nos ajudar a resolver tais problemas.
- -
- - - - - - - - - - - - -
Pré-requisitos:Conhecimentos básicos de informática e sobre os fundamentos do JavaScript.
Objetivo:Ganhar familiaridade com o que é o Js assíncrono e como ele se difere do Js síncrono.
- -

JavaScript síncrono

- -

Para entendermos o que é o {{Glossary("asynchronous")}} JavaScript, nós primeiro temos que ter certeza que entedemos o que é o {{Glossary("synchronous")}} JavaScript. Essa seção revê um pouco das informações que nós vimos no artigo anterior.

- -

Muitas das funcionalidades que nós vimos em áreas anteriores são síncronas — você executa um código, e o reultado é retornado assim que o navegador puder. Vamos ver um exemplo simples (veja aqui, e veja o código fonte):

- -
const btn = document.querySelector('button');
-btn.addEventListener('click', () => {
-  alert('Você clicou em mim!');
-
-  let pElem = document.createElement('p');
-  pElem.textContent = 'Este é um novo parágrafo adicionado';
-  document.body.appendChild(pElem);
-});
-
- -

Neste bloco, as linhas são executadas uma após a outra:

- -
    -
  1. Nós damos referência à um elemento {{htmlelement("button")}} que já está disponível na DOM.
  2. -
  3. Nós adicionamos um evento de click, e quando ele for clicado ele fará o seguinte: -
      -
    1. Mostrar uma mensagem no alert().
    2. -
    3. Uma vez que o alert for dispensado, nós criamos um elemento {{htmlelement("p")}}.
    4. -
    5. Depois nós o preenchemos com um texto.
    6. -
    7. E finalmente, o adicionamos no body.
    8. -
    -
  4. -
- -

Enquanro cada operação é processada, nada mais pode acontecer — a renderização é pausada. Isso acontece porque o JavaScript opera em uma única thread (JavaScript é single threaded). Apenas uma coisa pode acontecer por vez, em uma única thread principal, e tudo é bloqueado até que a operação seja concluída.

- -

Então, no exemplo acima, depois que você tenha clicado no botão, o parágrafo não vai aparecer até que o botão OK do alert seja pressionado. Tente isso com o botão a seguir:

- - - -

{{EmbedLiveSample('Synchronous_JavaScript', '100%', '70px')}}

- -
-

Nota: É importante lembrar que, mesmo sendo muito útil para demonstar uma situação de blocking, o alert() não é de bom uso em aplicativos reais.

-
- -

Asynchronous JavaScript

- -

Por razões esclarecidas anteriormente (e.g. relativas ao blocking), muitas funcionalidades de APIs da Web agora usam código assíncrono na execução, especialmente aquelas que acessam ou buscam algum tipo de recurso de um dispositivo externo, como pegar um arquivo da rede, acessar um banco de dados e retornar dados dele, acessar uma stream de uma web cam, ou transmitir uma tela para um dispositivo VR.

- -

Por que é tão difícil trabalhar com isso usando códigos síncronos? Vamos dar uma olhada em um exemplo rápido. Quando você pega uma imagem de um servidor, você não pode retornar o resultado imediatamente. Isso significa que o pseudocódigo a seguir não poderia funcionar:

- -
let resposta = fetch('myImage.png');
-let blob = resposta.blob();
-// Mostra sua imagem na UI
- -

Isso acontece por que você não sabe quanto tempo a imagem levará para ser baixada, então quando você executar a segunda linha, ela vai resultar em um erro (provalvelmente sempre) porque a  resposta não estará disponível ainda. Você precisa que o seu código espere até que a resposta seja retornada antes de fazer algo com ela.

- -

Existem dois tipos principais de estilo de código assíncrono que você encontrará no código JavaScript, as callbacks com um estilo old-school e código em um estilo das promises mais recente. Nas seções abaixo, revisaremos cada um deles por vez.

- -

Callbacks assíncronas

- -

Callback são funções que são passada como parâmetros na chamada de outra função que vai executar código por trás do panos. Quando esse código por trás dos panos terminar de ser executado, a função callback será chamada para te informar que a tarefa foi finalizada ou que algo do seu interesse aconteceu. O uso das callbacks é um pouco antiquado agora, mas você ainda pode vê-las em um número de APIs comumente usadas.

- -

Um exemplo de uma callback async é o segundo parâmetro do método {{domxref("EventTarget.addEventListener", "addEventListener()")}} (como vimos em ação anteriormente):

- -
btn.addEventListener('click', () => {
-  alert('Você clicou em mim!');
-
-  let pElem = document.createElement('p');
-  pElem.textContent = 'Este é um novo parágrafo.';
-  document.body.appendChild(pElem);
-});
- -

O primeiro parâmetro é o tipo de evento a ser executado e o segundo parâmetro é uma função callback que é chamada quando o evento é disparado.

- -

Quando passamos uma função callback como um parâmetro em outra função, nós apenas estamos passando a rêferencia da função como argumento, ou seja, a função callback não é executada imediatamente. Ela é chamada de volta assíncronamente dentro do corpo da função que a contém, que é responsável por executar a função callback quando for necessário.

- -

Você pode escrever a sua própria função que contém uma callback facilmente. Vamos dar uma olhada em outro exemplo que carrega uma arquivo usando a API XMLHttpRequest (veja aqui, and veja o código fonte):

- -
function loadAsset(url, type, callback) {
-  let xhr = new XMLHttpRequest();
-  xhr.open('GET', url);
-  xhr.responseType = type;
-
-  xhr.onload = function() {
-    callback(xhr.response);
-  };
-
-  xhr.send();
-}
-
-function displayImage(blob) {
-  let objectURL = URL.createObjectURL(blob);
-
-  let image = document.createElement('img');
-  image.src = objectURL;
-  document.body.appendChild(image);
-}
-
-loadAsset('coffee.jpg', 'blob', displayImage);
- -

Aqui nós criamos uma função displayImage() que simplesmente representa um blob que foi passada à ela como uma URL de objeto, e depois cria uma imagem para mostrar a URL, adicionando-a ao <body> do documento. Entretando, nós criamos depois uma função loadAsset() que pega uma callback como parâmetro, junto com uma URL a ser buscada e um tipo para o conteúdo. Ela usa o XMLHttpRequest (abreviação: "XHR") para buscar o recurso na URL dada, para depois passar a resposta para a callback para fazer algo com isso. Neste caso a callback está esperando o XHR  terminar de baixar o recurso (usando o manipulador de eventos onload) antes de passá-lo para a callback.

- -

Callback são versáteis — elas não apenas lhe permitem controlar a ordem em que as funções são executadas e quais dados são passados entre elas, elas também podem passar dados para diferentes funçoes dependendo das circunstâncias. Então você pode ter ações diferentes para executar na resposta baixada, como processJSON(), displayText(), etc.

- -

Note que nem todas as callback são assíncronas — algumas são executadas de um modo síncrono. Um exemplo é quando nós usamos o método {{jsxref("Array.prototype.forEach()")}} para iterar sobre os itens de uma array (veja aqui, e a fonte):

- -
const gods = ['Apollo', 'Artemis', 'Ares', 'Zeus'];
-
-gods.forEach(function (eachName, index){
-  console.log(index + '. ' + eachName);
-});
- -

Neste exemplo nós iteramos sobra uma array de Deuses Gregos e imprimos o índice e seus valores no console. O parâmetro de forEach() é uma callback function, que por si só toma dois parâmetros: uma refêrencia ao nome da array e e os valores dos índices. Entretanto, ela não espera por algo para fazer a execução, pois isso acontece imediatamente

- -

Promises

- -

Promises são uma nova maneira de escrever código assíncrono que você verá em APIs Web modernas. Um bom exemplo disso é a API fetch(), que é basicamente uma versão mais moderna e eficiente de {{domxref("XMLHttpRequest")}}. Vamos dar uma olhada em um exemplo rápido, do nosso artigo de Pegando dados do servidor:

- -
fetch('products.json').then(function(response) {
-  return response.json();
-}).then(function(json) {
-  products = json;
-  initialize();
-}).catch(function(err) {
-  console.log('Fetch problem: ' + err.message);
-});
- -
-

Nota: Você pode encontrar a versão finalizada no GitHub (veja aqui, e também seja a execução).

-
- -

Aqui nós vemos fetch() pegando um único parâmetro — a URL de um recurso que você quer pegar da rede — e retornando uma promise. A promise é um objeto que representa a conclusão ou falha da operação assíncrona. Ela represente um estado intermediário, por assim dizer. É praticamente o jetio do navegador de dizer "Eu prometo voltar para você com a resposta o mais rápido possível", daí o nome "promessa".

- -

Você pode levar um tempo para se acostumar com esse conceito; Ele se parece um pouco com o {{interwiki("wikipedia", "Gato de Schrödinger")}} em ação. Nenhum dos possíveis resultados aconteceu ainda, então a operação fetch está esperando pelo resultado do navegador que vai completar a operação em algum ponto no futuro.

- -

Nós temos três blocos de código encadeados ao fim do fetch():

- - - -
-

Nota: Você vai aprender mais sobre promises mais tarde no módulo, então não se preocupe se você não entendeu muito bem.

-
- -

A fila de eventos

- -

Operações assíncronas como as promises são colocadas em uma fila de eventos, que é executada depois que a main thread terminar de ser processada. As operações serão completadas assim que for possível e depois retornam seus resultados para o ambiente JavaScript.

- -

Promises versus callbacks

- -

As promises tem algumas semelhanças com as callbacks. Elas são basicamente um objeto retornado em que você vincula funções callback, ao invés de passar as callbacks para uma função.

- -

Entretanto, as promises são feitas especificamente para lidarmos com operações async, e ter muitas vantagens sobre as velhas callbacks:

- - - -

A natureza do código assíncrono

- -

Vamos explorar um exemplo que ilustra a natureza do código assíncrono, mostrando o que pode acontecer quando nós não estamos cientes da ordem de execução e dos problemas em tentar tratar código async como código síncrono. O exemplo a seguir é muito similar ao que vimos antes (veja aqui, e a fonte). Uma diferença e que nós icluimos um número de declarações {{domxref("console.log()")}} para ilustrar na ordem que você pensa que o código fosse executado.

- -
console.log ('Starting');
-let image;
-
-fetch('coffee.jpg').then((response) => {
-  console.log('It worked :)')
-  return response.blob();
-}).then((myBlob) => {
-  let objectURL = URL.createObjectURL(myBlob);
-  image = document.createElement('img');
-  image.src = objectURL;
-  document.body.appendChild(image);
-}).catch((error) => {
-  console.log('There has been a problem with your fetch operation: ' + error.message);
-});
-
-console.log ('All done!');
- -

O navegador vai começar a executar o código, veja a primeira declaração console.log()(Starting) e a execute, e depois crie a variável image.

- -

Depois a segunda linha vai começar a ser executada começando com o bloco fetch(), mas desde que fetch() é executado assíncronamente sem bloquear nada, a execução do código continua mesmo depois do código promise, alcançando a última declaração console.log()(All done!) e imprimindo a no console.

- -

Uma vez que o bloco fetch() tenha terminado a sua execução e retornado seu resultado com os blocos .then(), nós finalmente veremos a segunda mensagem console.log() (It worked :)) appear. Então as mensagens aparecem nessa ordem:

- - - -

Se isso te deixa confuso, então considere o exemplo a seguir:

- -
console.log("registering click handler");
-
-button.addEventListener('click', () => {
-  console.log("get click");
-});
-
-console.log("all done");
- -

Isso é bem similar no comportamento — a primeira e a terceira mensagens console.log() são mostradas imediatamente, mas a segunda está bloqueada até alguém clique no botão. O exemplo anterior funciona da mesma forma, exceto que no caso a segunda mensagem está bloqueada na promise pegando um recurso e depois o mostra na tela.

- -

Em um exemplo mais superficial, esse tipo de configuração poderia causar um problema — você não pode incluir um bloco async que retorna um resultado, que depois depende de um código síncrono. Você não pode garantir que a função async vai retornar antes que o navegador processou o bloco síncrono.

- -

Para ver isso em ação, tente fazer uma cópia local do nosso exemplo, e mudar o terceiro console.log() para o seguinte:

- -
console.log ('Tudo Feito! ' + image.src + 'mostrada.');
- -

Agora você deve ter um erro no seu console ao invés da terceira mensagem:

- -
TypeError: image is undefined; can't access its "src" property
- -

Isso acontece porque o navegador tenta executar o terceiro console.log() e o bloco fetch() não terminou de ser executado e não foi dado  um valor para a variável image.

- -
-

Nota:Por razões de segurança, você não pode usar o fetch()  com arquivos do seu sistema local (ou executar operações localmente); para executar o exemplo acima você teria que rodá-lo em um servidor local.

-
- -

Aprendizado ativo: faça tudo async!

- -

Faça que o exemplo problemático de fetch() imprima três mensagens console.log() na tela na ordem desejada, você pode fazer a útima declaração console.log() assíncrona também. Isso pode ser feito colocando ela em outro bloco .then() encadeamo no final do segundo bloco, ou por simplesmente movê-lo para dentro do segundo bloco then().

- -
-

Note: If you get stuck, you can find an answer here (see it running live also). You can also find a lot more information on promises in our Graceful asynchronous programming with Promises guide, later on in the module.

-
- -

Conclusion

- -

In its most basic form, JavaScript is a synchronous, blocking, single-threaded language, in which only one operation can be in progress at a time. But web browsers define functions and APIs that allow us to register functions that should not be executed synchronously, and should instead be invoked asynchronously when some kind of event occurs (the passage of time, the user's interaction with the mouse, or the arrival of data over the network, for example). This means that you can let your code do several things at the same time without stopping or blocking your main thread.

- -

Whether we want to run code synchronously or asynchronously will depend on what we're trying to do.

- -

There are times when we want things to load and happen right away. For example when applying some user-defined styles to a webpage you'll want the styles to be applied as soon as possible.

- -

If we're running an operation that takes time however, like querying a database and using the results to populate templates, it is better to push this off the main thread and complete the task asynchronously. Over time, you'll learn when it makes more sense to choose an asynchronous technique over a synchronous one.

- - - -

{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}

- -

In this module

- - -- cgit v1.2.3-54-g00ecf