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?
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?
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;
}