Exercício fácil: async e await

Async e await são extensões das promises. Quando uma função assíncrona é chamada, ela retorna uma promise. Uma função assíncrona pode conter uma palavra-chave await, que pausa a execução da função e espera pela resolução da promise passada, retomando a execução após a resolução da promise e retornando o valor resolvido. A proposta das funções async/await é simplificar o uso de promises. Assim como promises são similares a callbacks estruturados, as funções async/await são similares à junção de generators com promises. Caso você não conheça o async/await, recomendo que antes de prosseguir, leia este artigo: Entenda o async e await.

Dito isto, vamos ao exercício:

Passo 1:

Crie uma função que após 5 segundos, dobre o resultado do número passado como parâmetro. Essa função deverá retornar uma promise. Use o setTimeOut como temporizador.

O corpo da função abaixo servirá como base para este exercício:

function dobrarEm5Segundos(x) {
  return new Promise( => {
    setTimeout(() => {      
    });
  });
}

Realizado este passo, podemos seguir adiante:

Passo 2:

Crie uma função assíncrona que irá receber um parâmetro x. Crie três variáveis: a, b e c dentro do corpo da função. Cada uma dessas variáveis receberá um await da função do passo anterior. Você deve passar como parâmetros dessa função os número 10, 20 e 30, respectivamente.

Retorne a soma de todos esses elementos, inclusive o parâmetro da função assíncrona.

async function addAsync(x) {
  let a;
  let b;
  let c;
  return;
}

Para mostrar o resultado no console, utilize o .then():

addAsync().then(() => {
  console.log();
});

Você pode realizar o download do exercício resolvido aqui:

[download id=”3580″]

Gostou deste exercício? Comente abaixo:

Entenda o async e await

Async e await são extensões das promises. Caso você não conheça promises, acesse o artigo seguinte e realize a leitura antes de prosseguir com async e await: https://www.mundojs.com.br/2020/03/02/o-que-sao-e-como-criar-promises/.

Quando uma função assíncrona é chamada, ela retorna uma promise. Uma função assíncrona pode conter uma palavra-chave await, que pausa a execução da função e espera pela resolução da promise passada, retomando a execução após a resolução da promise e retornando o valor resolvido.

A proposta das funções async/await é simplificar o uso de promises. Assim como promises são similares a callbacks estruturados, as funções async/await são similares à junção de generators com promises.

async:

A palavra async antes de uma função significa que a função sempre retorna uma promise. Outros valores serão agrupados em uma promise resolvida automaticamente. Por exemplo, esta função async retorna uma promise resolved com a string “Ola Mundo”:

async function funcaoAsync() {
    return 'Ola Mundo';
}

funcaoAsync().then(console.log);

E nós podemos retornar uma promise explicitamente, que retornaria a mesma coisa:

async function funcaoAsync(){
    return Promise.resolve('Ola Mundo')
}

funcaoAsync().then(console.log);

Então, o async garante que a função retorne uma promise.

Mas há outra palavra-chave, chamada await, que funciona apenas dentro de funções assíncronas.

await:

A palavra-chave await faz com que a função espere até que a promise seja estabelecida e retorne o seu resultado. Confira neste exemplo o seu funcionamento:

async function funcaoAsyncAwait() {
    // Criaremos uma promise que retornará a string 
    // "Promise concluída", após o tempo de 5 segundos.
    let promise = new Promise((resolve, reject) => {
        setTimeout(() => resolve("Promise concluída!"), 5000)
    });

    // Esta variavel resultado recebe o resultado da promise, após sua conclusão.
    let resultado = await promise;
    console.log(resultado);
}

funcaoAsyncAwait();

Nesta função, a execução “pausa” e somente retorna quando passa o tempo de execução da promise. Literalmente falando, o await aguarda a conclusão da promise para retornar o resultado! Então, você verá a string “Promise concluída” após 5 segundos de execução, que é o tempo que estabelecemos para a conclusão da promise.

Observação: Não podemos utilizar o await em função síncronas. Ele funciona somente em funções assíncronas, então, precisamos ter o async em nossa function.

Continue lendo “Entenda o async e await”

O que são e como criar Promises:

Você sabe o que são promises?

Promises vem do termo “promessa”, que representa um valor que pode estar disponível em algum momento no futuro, no presente, ou nunca estar disponível. Ele é um objeto utilizado em processamento assíncrono. Um promise representa um proxy para um valor não necessariamente conhecido, permitindo uma associação de métodos de tratamento para eventos em uma ação assíncrona na hipótese de sucesso ou falha, permitindo que o método assíncrono retorne uma “promessa” ao valor em algum momento no futuro.

Quais são os estados de um promise?

  • pending (estado: pendente): O promise ainda não foi rejeitada, nem realizada. É o estado inicial;
  •  fulfilled (estado: realizado): O promise obteve sucesso na operação;
  • rejected (estado: rejeitado): O promise falhou na operação;
  • settled (estado: estabelecido): O promise foi estabelecido. Significa que o promise foi realizado ou rejeitado.

Sintaxe:

new Promise (/* executor */ function (resolve, reject) { … });

O executor é uma função que recebe os argumentos resolve e reject. O executor é chamado antes que o construtor de Promise retorne o objeto criado. As funções resolve e reject, quando chamadas, resolvem ou rejeitam (respectivamente) a promessa. Quando estiver concluído o trabalho assíncrono, o executor chama as funções resolve ou reject para definir o estado da promise.

Uma promise pode se tornar realizada ou rejeitada. Com a ocorrência de algum desses estados, o método them do Promise é chamado, e ele chama o método associado ao estado (resolved ou rejected).

O que é composição?

São métodos encadeados. Isso pode ocorrer com os métodos Promise.prototype.then e Promise.prototype.catch, já que ambos retornam promises que podem ser encadeadas.

Métodos:

  • Promise.all(lista): Retorna uma promise que é resolvida quando todas as promises no argumento forem resolvidas ou rejeitada quando uma das promises do argumento for rejeitada. É um método útil para agregar resultados de múltiplas promises.
  • Promise.race(lista): Retorna uma promise que resolve ou rejeita assim que uma das promises do argumento resolve ou rejeita.
  • Promise.reject(motivo): Retorna um promise que foi rejeitado por algum motivo.
  • Promise.resolve(valor): Retorna um promise que foi resolvido com dado valor. Se o valor for thenable (possuindo um método then), a promise retornada seguirá este metodo. Caso contrário, a promise será realizada com o valor.

Criando uma promise:

// Vejamos se a mãe está feliz. Utilize true para sim e false para não
let maeEstaFeliz = false;

// primeira promise que criaremos
let ganharTelefoneNovo = new Promise(
    (resolve, reject) => {
        if (maeEstaFeliz) {
            let telefone = {
                marca: 'iPhone',
                cor: 'Branco'
            };
            resolve(telefone);
        } else {
            let razao = new Error('Mãe não está feliz');
            reject(razao);
        }

    }
);

// Agora criaremos a segunda promise
async function mostrarTelefoneNovo(telefone) {
    return new Promise(
        (resolve, reject) => {
            var message = 'Hey cara, eu tenho um novo ' +
                telefone.marca + ' ' + telefone.cor;

            resolve(message);
        }
    );
};

// chamando nossa promise
async function perguntarParaMae() {
    try {
        console.log('Antes de perguntar para a mãe');

        let telefone = await ganharTelefoneNovo;
        let message = await mostrarTelefoneNovo(telefone);

        console.log(message);
        console.log('Depois de perguntar para a mãe');
    }
    catch (error) {
        console.log(error.message);
    }
}

(async () => {
    await perguntarParaMae();
})();

Gostou deste artigo? Comente abaixo!

Referências:

 

Como usar o setInterval

setInterval e clearInterval():

O setInterval() é uma função temporizadora. Ela executa uma função de retorno após determinado tempo. A função setInterval() executará infinitamente, até que você execute a função clearInterval().

Se você é iniciante, você pode pular a explicação Como funciona.

Como funciona?

Sendo uma função assíncrona, a instrução a ser executada é lançada no Event Loop. Mas o que é Event Loop? É uma instrução síncrona, ou seja, quando ela estiver executando, a thread ficará bloqueada e, assim que terminar, a próxima instrução é executada. Como o setInterval() executará infinitamente, sabemos que ele adicionará uma instrução ao Event Loop a cada quantia de tempo que for definida.

Definição:

O setInterval() chama uma função em intervalos de tempo definidos. Ele continuará chamando a função até que o clearInterval() seja chamado, ou que a página seja fechada.

Sintaxe:

// sintaxe da função setInterval, que define um temporizador
// que disparará uma ação definida em tempo estipulado
setInterval(function, miliseconds, parameter1, parameter2, …);
Onde:

function: é a função que será executada;

miliseconds: é o intervalo em milisegundos(ms) em que o código será executado. Se o valor especificado for menor que 10, o valor 10 será utilizado.

parameter: parâmetros para passar para a função.

Exemplo:

<!DOCTYPE html>
<html lang="pt-br">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>setInterval() e clearInterval()</title>
</head>

<body>
    <button id="btn">Clique aqui para iniciar</button>
    <script src="main.js"></script>
</body>

</html>
E no JavaScript:
// Crie uma variável
let variavel;

// Crie uma função, utilizando essa variável para 
// declarar o intervalo em que será disparado.
function minhaFuncao() {
    variavel = setInterval(consoleLog, 2000);
}
// Mensagem que será mostrada no console
function consoleLog() {
    console.log("Ola mundo!");
}

// Função será chamada utilizando o evento onclick
document.getElementById("btn").onclick = minhaFuncao;

O clearInterval() limpa o timer configurado pela função setInterval(). Ele desativa a função e não executa a função definida pelo temporizador.

Sintaxe:

// Função clearInterval travará a execução do setInterval
// bloqueando a ação definida pelo temporizador
clearInterval(id_do_setInterval)

Exemplo:

<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>setInterval() e clearInterval()</title>
</head>
<body>
    <button id="btn">Clique aqui para iniciar</button>
    <button id="btn2">Clique aqui para parar</button>
    <script src="main.js"></script>
</body>
</html>
E no JavaScript:
// Crie uma variável
let variavel;

// Crie uma função, utilizando essa variável para 
// declarar o intervalo em que será disparado.
function minhaFuncao() {
    variavel = setInterval(consoleLog, 2000);
}
// Mensagem que será mostrada no console
function consoleLog() {
    console.log("Ola mundo!");
}

// Função que será executada para bloquear
// a ação do temporizador definido no setInterval
function pararFuncao() {
    clearInterval(variavel);
}

// Função será chamada utilizando o evento onclick
document.getElementById("btn").onclick = minhaFuncao;
document.getElementById("btn2").onclick = pararFuncao;

Gostou deste artigo? Deixe o seu comentário abaixo:

Loop for com espera entre iterações

Recentemente tive uma duvida, como fazer para que um for tivesse esperasse alguns segundos entre cada iteração? Supodo que eu queira exibir um alerta em 10 vezes a de 5 em cindo segundos, como posso fazer com que o JavaScript espere estes 5 segundos?

Existem timers em JavaScript, como setInterval e setTimeout. SetInterval é um método de execução de código baseado em intervalo de tempo que tem a capacidade nativa de executar repetidamente um script especificado quando o intervalo é atingido. setTimeout é um método de execução de código baseado em tempo que executará um script apenas uma vez quando o intervalo for atingido.

Tendo isto em mente, a primeira coisa que tentei foi colocar o setTimeout dentro do for para tentar obter essa espera

function timeoutFunction()
{
  console.log("Iniciando Teste");
  for(i = 0; i < 10; i++) {
    setTimeout(function () {
      console.log("Teste "+i);
    }, 5000);
  }
}
timeoutFunction();

Após o primeiro log, há um atraso de 5s, mas quando os logs dentro do setTmeout ocorrem em grupo

Por que isso acontece?

A função setTimeout() é uma função que roda em outra thread e por isso ela não bloqueia a execução do for, ou seja a função é invocada e o código segue executando sem precisar esperar que ela termine. Com isso ele executará as 10 execuções em questão de milisegundos e todos os tempos de espera ocorreram praticamente juntos.

Como adicionar o delay no loop for?

A Expressão de Função de Chamada Imediata (IIFE – Immediate Invoking Function Expression) pode ser usada para obter o que queremos. Sua sintaxe funciona da seguinte forma:

(function () {

})();

O IIFE chama imediatamente uma função. Isso significa simplesmente que a função é executada imediatamente após a conclusão da definição. Se utilizarmos essa função, obteremos a saída desejada

console.log("Iniciando Teste");
for (var i = 0; i < 10; i++) {
  (function (i) {
    setTimeout(function () {
      console.log("Teste" + i);
    }, 5000*i);
  })(i);
};

O código acima, mesmo que você nunca tenha usado uma IIFE é simples, nó passamos a varável “i” como parametro da função (pois se tentarmos acessa-lo direto do loop o settimeout conseguirá obter apenas a iteração final com i = 9) e fazemos uma matemática simples para que as funções executem de forma a serem 5 segundos X nº iteração.

JavaScript: Melhoras de perfomance assíncrona

A equipe do V8 JavaScript anuncia melhorias para otimizar as funções e promessas assíncronas. A equipe também aprimorou a experiência de depuração do código assíncrono, um ponto problemático comum para desenvolvedores de JavaScript.

A introdução de promessas no ES2015 e a introdução posterior de funções assíncronas e a iteração assíncrona do ES2018 tornam a criação de código assíncrono muito mais eficiente do que o uso de callbacks. No entanto, até recentemente, o uso desses novos recursos não era eficiente.

A equipe do V8 também explorou o desempenho do código-fonte do mundo real, observando o uso com estruturas de middleware como hapi, koa e trek, que usam promessas e funções assíncronas. Com as recentes mudanças no V8, o desempenho ao usar essas estruturas melhorou significativamente.

O V8 introduziu várias mudanças para levar a melhorias de desempenho assíncrono, incluindo o TurboFan, um novo compilador de otimização, e o Orinoco, um novo coletor de lixo, movendo o GC para fora do thread principal para melhorar o processamento de pedidos. Além disso, houve um erro dentro do Node.js 8 que levou à espera de pular microtricks em alguns casos.

O trabalho de desempenho levou a alguns patches propostos para melhorar a especificação de funções assíncronas, o que deve melhorar o desempenho não apenas no V8, mas em todos os mecanismos JavaScript. Essas alterações incluem a remoção de dois microticks extras e a remoção de uma promessa descartável de funções assíncronas.

Com as atualizações recentes para o código-fonte V8 e refinamentos propostos para a especificação de funções assíncronas, async / wait agora supera o código promocional pela primeira vez reduzindo a sobrecarga das funções assíncronas.

Para facilitar a depuração, o Chrome DevTools também melhora os rastreamentos de pilha para incluir a parte assíncrona do rastreamento de pilha.

O V8 é um mecanismo JavaScript de código aberto do Google que usa navegadores baseados no Chrome e no Chromium, bem como o Node.js. O V8 está disponível sob uma licença do estilo BSD. Contribuições são bem-vindas através do projeto V8 GitHub sob o código de conduta Chromium.

Utilizando Async Await com Expressjs

Hoje eu irei demonstrar como nós podemos utilizar Async/Await em um projeto Node.js com express.js.

O Objetivo desse artigo não será abordar o que é async e nem o porque utilizar ele (caso não saiba veja o artigo ES8: Funções Assíncronas), será algo rápido para demonstrar como trabalhar com ele em um projeto node com o framework expressjs.


Para pular a etapa de criação de um novo projeto, eu irei utilizar um que eu desenvolvi em um artigo anterior sobre:Criando uma API Node com Express.js. Caso você tenha interesse em clonar ele, segue o seu link no meu GitHub: node-express.

Para que possamos ter um cenário mais próximo do nosso dia a dia, eu irei fazer uma requisicão a uma URL externa. Existem muitos pacotes para isso, mas nesse artigo eu irei utilizar o pacote resquest.

Abra um terminal no seu computador e execute o comando abaixo:

npm install request --save-dev

O próximo passo será atualizar a nossa rota GET para que ela possa requisitar uma API externa. Para isso, abra o seu arquivo /src/controllers/personController.js e atualize ele com o trecho de código abaixo:

var request = require("request");

exports.get = async (req, res, next) => {
  console.log("chamando");
  await request("http://www.google.com", function(error, response, body) {
    res.json(body);
  });
};

Em seguida, execute o comando npm start no seu terminal, esse comando ira executar o projeto no seguinte endereço: http://localhost:3000/person.

Abra esse endereço no seu navegador.

Caso tudo esteja OK, você irá receber o resultado da imagem abaixo:

resultado node com Async Await

Bem simples né?

O objetivo desse artigo foi demonstrar como utilizar o Async/Await com Node e o Express.js. Espero que tenham gostado e até um próximo artigo pessoal.