Promessas em JavaScript foram uma revelação no JavaScript, oferecendo uma alternativa ao inferno de callbacks do JavaScript em que nos encontramos rapidamente. As promessas também nos permitiram introduzir e lidar melhor com tarefas assíncronas. Embora as promessas tenham sido uma melhoria em relação ao inferno do callback, elas ainda exigem muito thens, o que pode se tornar uma bagunça. Eu realmente gostei da função async e await para simplificar o tratamento de promessas. Vamos dar uma olhada no async e await!
Noções básicas rápidas
asyncé uma palavra-chave para a declaração da funçãoawaité usado durante o tratamento da promessaawaitdeve ser usado dentro de umasyncembora o Chrome agora suporte “nível superior”awaitasyncretornam uma promessa, independentemente do que oreturnseja o valor dentro da funçãoasync/awaite as promessas são essencialmente as mesmas sob o capô- Disponível agora na maioria dos navegadores, bem como no Node.js
Benefícios do async e await
- Seu código é mais simplista, preciso
- A depuração é mais fácil graças a menos retornos de chamada
- Conversão de promessa
then/catcho código é fácil - Seu código pode ser mais “top down”, com menos aninhamento
Básico async e await Ilustração
É sempre mais fácil aprender com um exemplo, portanto, vamos dar uma olhada em um exemplo muito simples async / await utilização:
// Function declared as async so await can be used
async function fetchContent() {
// Instead of using fetch().then, use await
let content = await fetch('/');
let text = await content.text();
// Inside the async function text is the request body
console.log(text);
// Resolve this async function with the text
return text;
}
// Use the async function
var promise = fetchContent().then(...);
Comece declarando a função como async; essa declaração permite que o await seja usado por dentro. O await é seguida por uma ação de promessa, que, obviamente, o fetch API é. A rotina assíncrona (fetch neste caso) é executada e a execução de outros códigos é interrompida (embora sem bloqueio) até que a ação assíncrona seja concluída. Em seguida, a função é resolvida com o return e uma promessa é retornada.
Essencialmente, o senhor consegue manter seu código “em linha” sem a necessidade de retornos de chamada. É o async simplificado!
Conversão do Promise Handling em await
É bem provável que o senhor queira atualizar seu código de promessa quando o tempo estiver disponível. Vamos examinar a atualização da promessa para await:
// Before: callback city!
fetch('/users.json')
.then(response => response.json())
.then(json => {
console.log(json);
})
.catch(e => { console.log('error!'); })
// After: no more callbacks!
async function getJson() {
try {
let response = await fetch('/users.json');
let json = await response.json();
console.log(json);
}
catch(e) {
console.log('Error!', e);
}
}
A conversão de cargas de thens para await é simples de executar e, com sorte, seu código parece um pouco sustentável!
async / await Padrões
Há várias maneiras de o senhor declarar async funções.
Função assíncrona anônima
let main = (async function() {
let value = await fetch('/');
})();
Declaração de função assíncrona
async function main() {
let value = await fetch('/');
};
Atribuição de função assíncrona
let main = async function() {
let value = await fetch('/');
};
// Arrow functions too!
let main = async () => {
let value = await fetch('/');
};
Função assíncrona como argumento
document.body.addEventListener('click', async function() {
let value = await fetch('/');
});
Objeto & Métodos de classe
// Object property
let obj = {
async method() {
let value = await fetch('/');
}
};
// Class methods
class MyClass {
async myMethod() {
let value = await fetch('/');
}
}
Como o senhor pode ver, adicionar async é muito fácil e se adapta a todos os fluxos de trabalho de criação de funções!
Tratamento de erros
O uso tradicional de promessas permite que o senhor use um catch para tratar a rejeição. Quando o usuário usa await, sua melhor opção é usar try/catch:
try {
let x = await myAsyncFunction();
}
catch(e) {
// Error!
}
O antigo try/catch não é tão glamouroso quanto o de uma promessa catch de uma promessa, mas é igualmente eficaz.
Paralelismo
Jake Archibald, do Google, fez excelentes observações no Documento sobre funções assíncronas sobre não ficar muito sequencial com suas awaits. A ideia é evitar o empilhamento de espera, quando possível, e, em vez disso, acionar as tarefas imediatamente e usar await após essas tarefas forem acionadas:
// Will take 1000ms total!
async function series() {
await wait(500);
await wait(500);
return "done!";
}
// Would take only 500ms total!
async function parallel() {
const wait1 = wait(500);
const wait2 = wait(500);
await wait1;
await wait2;
return "done!";
}
O primeiro bloco é ruim porque o segundo wait acontece depois do primeiro wait for concluído. O segundo bloco é um método melhor: acionar os dois wait e o então usar await ; fazer isso permite que as funções assíncronas ocorram simultaneamente!
Promise.all Equivalentes
Uma das minhas funções favoritas da API Promise é Promise.allque dispara um retorno de chamada quando todas as buscas são concluídas. Não há nenhum async / await equivalente, mas este post fornece um bom equivalente:
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
Lembre-se de que async / await são essencialmente iguais às promessas, portanto, estamos simplesmente aguardando que a promessa agregada seja resolvida!
Agora o senhor pode usar o async e await em todos os principais navegadores. Essas novas palavras-chave também estão disponíveis no Node.js; versões mais antigas do Node.js podem usar a palavra-chave transform-async-to-generator para usar o plug-in babel async e await hoje. As promessas ainda são excelentes, mas são mais fáceis de manter com o async e await!