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: 8Nesse 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: 8Aqui, 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: 12Tratamento 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: 16A 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: 16A chamada da operação assíncrona é colocada dentro do bloco try, e a ocorrência de um erro pode ser tratada no bloco catch.