Skip to content

Latest commit

 

History

History
171 lines (116 loc) · 5.13 KB

29.javascript_assincrono_moderno_com_async_e_await.md

File metadata and controls

171 lines (116 loc) · 5.13 KB

JavaScript assíncrono moderno com Async e Await

Índice

Introdução

O JavaScript evoluiu em muito pouco tempo de callbacks para promises (ES2015) e, desde o ES2017, o JavaScript assíncrono é ainda mais simples com a sintaxe async/await.

As funções assíncronas são uma combinação de promises e generators e, basicamente, são uma abstração de nível superior sobre promises. Deixe-me repetir: async/await é baseado em promises.

Por que o async/await foi introduzido?

Eles reduzem o clichê em torno de promises e a limitação "não quebre a cadeia" das promises de encadeamento.

Quando as promises foram introduzidas no ES2015, elas foram feitas para resolver um problema com código assíncrono, e resolveram, mas ao longo dos 2 anos que separam o ES2015 e o ES2017, ficou claro que as promises não poderiam ser a solução definitiva.

Promesas foram introduzidas para resolver o famoso problema do inferno de callbacks, mas elas introduziram complexidade por conta própria e complexidade de sintaxe.

Eles foram bons primitivos em torno dos quais uma sintaxe melhor poderia ser exposta aos desenvolvedores, então, quando chegasse a hora certa, obtivemos funções assíncronas.

Eles fazem o código parecer assíncrono, mas é assíncrono e não bloqueante nos bastidores.

Como isso funciona

Uma função assíncrona retorna uma promise, como nesse exemplo:

const doSomethingAsync = () => {
  return new Promise(resolve => {
    setTimeout(() => resolve('I did something'), 3000);
  });
};

Quando você deseja chamar esta função, você adiciona await e o código de chamada parará até que a promise seja resolvia ou rejeitada. Uma ressalva: a função do cliente deve ser definida como async (assíncrona). Aqui está um exemplo:

const doSomething = async () => {
  console.log(await doSomethingAsync());
};

Um rápido exemplo

Esse simples exemplo de async/await usado para executar uma função de forma assíncrona:

const doSomethingAsync = () => {
  return new Promise(resolve => {
    setTimeout(() => resolve('I did something'), 3000)
  })
}

const doSomething = async () => {
  console.log(await doSomethingAsync())
}

console.log('Before')
doSomething()
console.log('After')

Prometa todas as coisas

Anexar a palavra-chave async a qualquer função significa que a função retornará uma promise.

Mesmo que não esteja fazendo isso explicitamente, internamente fará com que retorne uma promise.

É por isso que este código é válido:

const aFunction = async () => {
  return 'test';
};

aFunction().then(alert); // This will alert 'test'

é o mesmo que:

const aFunction = () => {
  return Promise.resolve('test');
};

aFunction().then(alert); // This will alert 'test'

O código é mais simples de ler

Como você pode ver no exemplo acima, nosso código parece muito simples. Compare-o com o código usando promises simples, com funções de encadeamento e callback.

E este é um exemplo muito simples, os maiores benefícios surgirão quando o código for muito mais complexo.

Por exemplo, veja como você obteria um recurso JSON e o analisaria usando promises:

const getFirstUserData = () => {
  return fetch('/users.json') // get users list
    .then(response => response.json()) // parse JSON
    .then(users => users[0]) // pick first user
    .then(user => fetch(`/users/${user.name}`)) // get user data
    .then(userResponse => userResponse.json()); // parse JSON
};

getFirstUserData();

e aqui está a mesma funcionalidade só que usando await/async:

const getFirstUserData = async () => {
  const response = await fetch('/users.json'); // get users list
  const users = await response.json(); // parse JSON
  const user = users[0]; // pick first user
  const userResponse = await fetch(`/users/${user.name}`); // get user data
  const userData = await userResponse.json(); // parse JSON
  return userData;
};

getFirstUserData();

Múltiplas funções assíncronas em serie

As funções assíncronas podem ser encadeadas com muita facilidade e a sintaxe é muito mais legível do que com promises simples:

const promiseToDoSomething = () => {
  return new Promise(resolve => {
    setTimeout(() => resolve('I did something'), 10000)
  })
}

const watchOverSomeoneDoingSomething = async () => {
  const something = await promiseToDoSomething()
  return something + '\nand I watched'
}

const watchOverSomeoneWatchingSomeoneDoingSomething = async () => {
  const something = await watchOverSomeoneDoingSomething()
  return something + '\nand I watched as well'
}

watchOverSomeoneWatchingSomeoneDoingSomething().then(res => {
  console.log(res)
})

Fazer debugger mais fácil

As promises de depuração são difíceis porque depurador não passará por cima do código assíncrono.

Async/await torna isso muito fácil porque para o compilador é como código síncrono.