How does ES7 async/await work?

Asked

Viewed 545 times

13

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

1 answer

12


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

To illustrate I will leave here two Promises that I will 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 solved returns the title of Marcos' position. If it were written as Promise it would be:

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

Although the promise form code is shorter in the case, the async function code is much simpler to understand when reading the code. This becomes 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 the await in the user’s call, the promise would await the user’s marcos for 1 second and then call for pedro which would make the application wait for another second.

If I were using promises I’d 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 once again may be shorter, but it’s less readable, of course we can write more verbose using Promise that can become more readable, but when we’re talking about real code, Normally using async will make your code much more readable and potentially simpler.

Rejections with async:

It is possible to reject an async function result using throw valor, the result will be the same as using 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 function usuarioInvalido when called will be rejected, executing the usuarioInvalido().catch(erro => console.log(erro)) you can see the error.

But to ignore errors, you can use blocks of try-catch in async functions, 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;
}
  • 1

    Typescript (language that compiles for ES3, ES5 and ES6) solves async and await support with ES6 generating functions (I guess that’s how you say... coroutines?) and Promises.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.