How does ES7 async / await work?

9

ES7 allows you to use a new syntax to work with Promises known as async / await functions. How can I use these functions and how are they compared to functions that use Promises to process data sequences and in parallel?

    
asked by anonymous 24.08.2016 / 00:41

1 answer

10

The syntax of async functions are converted to Promises native to JavaScript, making it compatible with existing implementations.

For example, I'll leave here two Promises I'll use:

// Retorna um usuário depois de 1 segundo.
function usuario(id) {
  const users = {
    1: {id: 1, nome: 'Marcos'},
    2: {id: 2, nome: 'Pedro'}
  };
  return new Promise(resolve => {
    setTimeout(() => resolve(users[id]), 1e3);
  });
}

// Retorna o cargo depois de 2 segundos
function cargo(idUsuario) {
  const cargos = {
    1: { titulo: 'Sobrinho do chefe' },
    2: { titulo: 'XGH Evangelista' }
  };
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      let usuario = cargos[idUsuario];
      if (usuario) resolve(usuario);
      else reject('Usuário não existe!');
    }, 2e3);
  });
}

Now let's create some functions using async / await syntax.

Sequential:

async function cargoDoMarcos() {
  const user = await usuario(1);
  const cargo = await cargo(user.id);
  return cargo.title;
}

The above code will return a Promise, which when resolved returns the title of the Marcos post. If it were written as Promise it would be:

function cargoDoMarcos() {
  return usuario(1)
    .then(user => cargo(user.id);
}

Although the prompting code is shorter in the case, the async function code is much simpler to understand when reading the code. This is very clear when the code has several promises in sequence.

But what about parallel calls?

Parallel:

async function meusColegas() {
  // Chamei os dois sem o await
  let marcos = usuario(1);
  let pedro = usuario(2);

  // Agora eu vou usar esses objetos então vou esperar pela resposta deles:
  marcos = await marcos; // após 1 segundos vai continuar
  pedro = await pedro;   // já tem o pedro, imediatamente vai continuar
  return '${marcos.nome} e ${pedro.nome}';
}

If we used await on the user's call, the promise would wait for the user of marcos for 1 second and then call for pedro which would cause the application to wait for another second.

If you were using promises it would look like this:

function meusColegas() {
  let marcos = usuario(1);
  let pedro = usuario(2);
  return Promises.all([marcos, pedro])
    .then(colegas => '${colegas[0].nome} e ${colegas[1].nome}');
}
Writing in Promise format again may be shorter, but it's less readable, of course we can write more verbose using Promise which may become more readable, but when we're talking about actual codes, we usually use async goes make your code much more readable and potentially simpler.

Rejections with async:

You can reject an async function result using throw valor , the result will be the same as Promise.reject(valor) .

async function nomeDoUsuarioInvalido() {
  const usuario = await usuario(3);
  // A partir desta linha, nada será executado, pois o usuario(3) foi rejeitado.
  return usuario.nome;
}

The usuarioInvalido function when calling is going to be rejected by running usuarioInvalido().catch(erro => console.log(erro)) you can see the error.

But to ignore errors, you can use try-catch blocks in async functions, for example:

async function nomeDoUsuarioInvalido() {
  let usuario;
  let nome;
  try {
    usuario = await usuario(3);
    // A proxima linha será ignorada
    nome = usuario.nome;
  } catch (erro) {
      // erro = 'Usuário não existe!'
      nome = 'Ninguém';
  }
  // Este código será executado e vai retornar 'Ninguém'
  return nome;
}
    
24.08.2016 / 00:41