Async/Await e Promises: Trabalhando com Operações Assíncronas em JavaScript

No desenvolvimento de aplicações modernas, especialmente aquelas que interagem com APIs ou executam operações de entrada e saída (I/O), o uso de operações assíncronas é crucial.

Para quem não está familiarizado com o conceito, entrada e saída na computação significa que uma solicitação é feita pelo usuário (entrada), processada pelo computador, e então uma resposta é retornada (saída).

O JavaScript, por ser uma linguagem single-threaded, precisa de mecanismos eficientes para lidar com essas operações sem bloquear a execução do restante do código.

Dois desses mecanismos são a sintaxe Async/Await e Promises.

Quer entender como o JavaScript assíncrono funciona? Você está no lugar certo.

Neste conteúdo, exploraremos os principais conceitos e aplicações do Async/Await e Promises

Requisição (Request) e Resposta (Response)

Para entendermos Async/Await e Promises, é importante compreendermos as requisições (request) e respostas (response) e também as definições dos comportamentos síncrono e assíncrono.

Uma requisição é uma solicitação enviada do cliente para o servidor, enquanto uma resposta é a informação que o servidor envia de volta ao cliente.

Esse ciclo de requisição e resposta é fundamental na comunicação entre diferentes partes de uma aplicação, especialmente em operações assíncronas.

Async/Await e Promises: Síncrono e Assíncrono

Em operações síncronas, cada tarefa é executada de forma sequencial, ou seja, uma tarefa só começa depois que a anterior é concluída.

Isso pode causar bloqueios no sistema, especialmente em operações de I/O que podem levar tempo.

Já em operações assíncronas, as tarefas podem ser iniciadas e, enquanto aguardam sua conclusão, outras tarefas podem continuar a ser executadas.

Isso permite uma execução mais eficiente e responsiva, crucial para aplicações modernas que precisam lidar com múltiplas operações simultaneamente.

O que são Promises?

Async/Await e Promises são uma forma de lidar com operações assíncronas em JavaScript.

Elas representam um valor que pode estar disponível agora, no futuro, ou nunca.

Isso pode parecer confuso, mas vamos simplificar. Promises permitem que seu código continue a ser executado enquanto elas lidam com suas requisições.

As ações das Promises podem ocorrer imediatamente, no futuro, após a execução do seu código síncrono, ou nunca, caso sejam rejeitadas.

Tudo isso acontece em segundo plano, sem impedir que outras tarefas do programa sejam executadas.

Uma Promise tem três estados:

  • Pending (pendente): A operação ainda não foi concluída.
  • Fulfilled (resolvida): A operação foi concluída com sucesso.
  • Rejected (rejeitada): A operação falhou.

Criando e Utilizando Promises

Para criar uma Promise, utilizamos o construtor Promise, passando uma função que recebe dois parâmetros: resolve e reject.

Esses parâmetros são funções que determinam o estado da Promise.

const minhaPromise = new Promise((resolve, reject) => {
    let sucesso = true;
    if (sucesso) {
        resolve("Operação concluída com sucesso!");
    } else {
        reject("Operação falhou.");
    }
});

Para utilizar uma Promise, usamos os métodos then e catch.

O método then é chamado quando a Promise é resolvida, e o catch é chamado quando ela é rejeitada.

minhaPromise.then((mensagem) => {
    console.log(mensagem);
}).catch((erro) => {
    console.error(erro);
});

Promises em Cadeia

Podemos encadear múltiplas Promises para executar operações sequencialmente.

Isso é útil para realizar uma série de operações assíncronas onde cada uma depende da anterior.

const primeiraPromise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("Primeira operação concluída!"), 1000);
});

primeiraPromise.then((mensagem) => {
    console.log(mensagem);
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve("Segunda operação concluída!"), 1000);
    });
}).then((mensagem) => {
    console.log(mensagem);
}).catch((erro) => {
    console.error(erro);
});

Async/Await e Promises: Simplificando Promises

Embora as Promises sejam poderosas, seu uso extensivo pode tornar o código complexo e difícil de ler.

A sintaxe async/await foi introduzida no ECMAScript 2017 (ES8) para simplificar o trabalho com operações assíncronas.

Como Funciona o Async/Await

A palavra-chave async é usada para definir uma função assíncrona.

Dentro dessa função, podemos usar a palavra-chave await para pausar a execução até que uma Promise seja resolvida.

É importante usar await corretamente para pausar a execução.

Caso contrário, a Promise pode permanecer pendente, o que é um erro comum ao começar a aprender sobre o uso de Promises.

async function minhaFuncaoAssincrona() {
    try {
        let mensagem = await minhaPromise;
        console.log(mensagem);
    } catch (erro) {
        console.error(erro);
    }
}

Exemplo Prático com Async/Await

Vamos criar um exemplo prático que faz uma chamada a uma API utilizando fetch e processa a resposta usando async/await.

async function buscarDados() {
    try {
        let resposta = await fetch("https://api.exemplo.com/dados");
        if (!resposta.ok) {
            throw new Error("Erro na requisição");
        }
        let dados = await resposta.json();
        console.log(dados);
    } catch (erro) {
        console.error("Erro:", erro);
    }
}

buscarDados();

Comparação Entre Promises e Async/Await

A principal vantagem do async/await é que ele torna o código mais legível e fácil de entender, especialmente quando lidamos com várias operações assíncronas em sequência.

Compare os dois trechos de código abaixo:

Usando Promises

fetch("https://api.exemplo.com/dados")
    .then(resposta => {
        if (!resposta.ok) {
            throw new Error("Erro na requisição");
        }
        return resposta.json();
    })
    .then(dados => {
        console.log(dados);
    })
    .catch(erro => {
        console.error("Erro:", erro);
    });

Usando Async/Await

async function buscarDados() {
    try {
        let resposta = await fetch("https://api.exemplo.com/dados");
        if (!resposta.ok) {
            throw new Error("Erro na requisição");
        }
        let dados = await resposta.json();
        console.log(dados);
    } catch (erro) {
        console.error("Erro:", erro);
    }
}

buscarDados();

Tratamento de Erros

O tratamento de erros em Promises é feito utilizando o método catch.

Com async/await, podemos usar try/catch para capturar e lidar com erros.

No async/await, a sintaxe try/catch é amplamente utilizada para tratamento de erros.

Esse método é comum em diversas linguagens de programação, incluindo o próprio JavaScript, e é usado para tratar erros de forma geral.

Tratamento de Erros com Promises

minhaPromise
    .then(mensagem => {
        console.log(mensagem);
    })
    .catch(erro => {
        console.error("Erro:", erro);
    });

Tratamento de Erros com Async/Await

async function executar() {
    try {
        let mensagem = await minhaPromise;
        console.log(mensagem);
    } catch (erro) {
        console.error("Erro:", erro);
    }
}

executar();

Conclusão

Operações assíncronas são uma parte fundamental do desenvolvimento em JavaScript, especialmente quando trabalhamos com chamadas de rede e outras operações I/O.

Promises fornecem uma forma robusta de lidar com essas operações, mas podem tornar o código verboso e difícil de seguir quando usadas extensivamente.

A introdução do async/await simplificou significativamente o trabalho com operações assíncronas, permitindo escrever código mais limpo e legível.

Ao entender e utilizar esses conceitos, você pode melhorar a eficiência e a manutenção do seu código JavaScript.

Lembre-se de que, embora async/await torne o código mais simples, as Promises ainda são a base por trás dessa sintaxe, e um bom entendimento de ambas as abordagens é essencial para qualquer desenvolvedor JavaScript.

Não deixe de comentar o que você acha sobre essa tecnologia. Compartilhe suas experiências ou opiniões sobre Promises em JavaScript conosco.

Marcos R.S
Marcos R.S

Olá, pessoal! Sou Marcos, apaixonado por aprender, especialmente sobre tecnologia. Estou sempre em busca de lapidar os conhecimentos que já possuo e adquirir novos. Atuo com análise e desenvolvimento de sistemas, sou graduando em Sistemas de Informação e tenho formação técnica em Informática.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *