Como Usar async e await em JavaScript
A introdução do padrão ES2017 no JavaScript trouxe dois novos operadores: async
e await
, que visam simplificar o trabalho com promises.
O operador async
define uma função assíncrona, que se espera executar uma ou mais tarefas assíncronas:
async function nomeDaFuncao() {
// operações assíncronas
}
Dentro de uma função assíncrona, podemos usar o operador await
. Ele é colocado antes da chamada de uma operação assíncrona que representa um objeto Promise
:
async function nomeDaFuncao() {
await operacaoAssincrona();
}
O operador await
pausa a execução da função assíncrona até que a operação assíncrona (objeto Promise
) retorne um resultado.
Vale notar que o operador await
só pode ser usado dentro de funções definidas com o operador async
.
Vamos começar com um exemplo simples usando Promise
:
function sum(x, y) {
return new Promise(function (resolve) {
const result = x + y;
resolve(result);
});
}
sum(5, 3).then(function (value) {
console.log("Resultado da operação assíncrona:", value);
}); // Resultado da operação assíncrona: 8
Nesse caso, a função sum()
representa uma tarefa assíncrona. Ela recebe dois números e retorna um objeto Promise
, onde a soma desses números é realizada. O resultado da soma é passado para a função resolve()
. No método then()
, podemos obter esse resultado e realizar diversas ações com ele.
Agora, vamos reescrever esse exemplo usando async
/await
:
function sum(x, y) {
return new Promise(function (resolve) {
const result = x + y;
resolve(result);
});
}
// versão simplificada
// function sum(x, y) { return Promise.resolve(x + y);}
async function calculate() {
const value = await sum(5, 3);
console.log("Resultado da operação assíncrona:", value);
}
calculate(); // Resultado da operação assíncrona: 8
Aqui, definimos a função assíncrona calculate()
com o operador async
:
async function calculate() {
...
}
Dentro da função, chamamos a operação assíncrona sum()
, passando alguns valores para ela. O operador await
é aplicado a essa função. Com o await, não há necessidade de chamar o método then()
da Promise
. O resultado retornado pela Promise pode ser obtido diretamente da chamada da função sum
e atribuído a uma constante ou variável:
const value = await sum(5, 3);
Então, podemos chamar a função calculate()
como qualquer outra função e executar todas as suas ações:
calculate();
Vale destacar que uma função definida com o operador async
cria implicitamente um objeto Promise. Portanto, ela também pode ser usada como uma Promise
:
function sum(x, y) {
return new Promise(function (resolve) {
const result = x + y;
resolve(result);
});
}
async function calculate() {
const result = await sum(5, 3);
return result;
}
calculate().then((value) => console.log("Resultado da operação assíncrona:", value));
Execução Sequencial de Operações Assíncronas
Uma função assíncrona pode conter várias operações assíncronas, às quais se aplica o operador await
. Nesse caso, todas as operações assíncronas serão executadas sequencialmente:
function sum(x, y) {
return new Promise(function (resolve) {
const result = x + y;
resolve(result);
});
}
async function calculate() {
const value1 = await sum(5, 3);
console.log("Resultado da 1ª operação assíncrona:", value1);
const value2 = await sum(6, 4);
console.log("Resultado da 2ª operação assíncrona:", value2);
const value3 = await sum(7, 5);
console.log("Resultado da 3ª operação assíncrona:", value3);
}
calculate();
// Resultado da 1ª operação assíncrona: 8
// Resultado da 2ª operação assíncrona: 10
// Resultado da 3ª operação assíncrona: 12
Tratamento de Erros
Para tratar erros que podem ocorrer durante a execução de uma operação assíncrona, usamos a estrutura try
..catch
..finally
.
Por exemplo, vejamos o seguinte código usando Promise
:
function square(str) {
return new Promise((resolve, reject) => {
const n = parseInt(str);
if (isNaN(n)) reject("Not a number");
else resolve(n * n);
});
}
function calculate(str) {
square(str)
.then((value) => console.log("Result:", value))
.catch((error) => console.log(error));
}
calculate("g8"); // Not a number
calculate("4"); // Result: 16
A função square()
recebe um valor, que é convertido para número dentro de uma Promise
. Se a conversão for bem-sucedida, o quadrado do número é retornado. Se o valor passado não for um número, um erro é retornado.
Ao chamar a função square()
, podemos tratar o erro com o método catch()
.
Agora, reescrevemos o exemplo usando async
/await
:
function square(str) {
return new Promise((resolve, reject) => {
const n = parseInt(str);
if (isNaN(n)) reject("Not a number");
else resolve(n * n);
});
}
async function calculate(str) {
try {
const value = await square(str);
console.log("Result:", value);
} catch (error) {
console.log(error);
}
}
calculate("g8"); // Not a number
calculate("4"); // Result: 16
A chamada da operação assíncrona é colocada dentro do bloco try
, e a ocorrência de um erro pode ser tratada no bloco catch
.