In JavaScript, async and await are a syntax for writing asynchronous code that is simpler easier to read and maintain than previous alternatives (like callbacks and promises)
Introduced in ECMAScript 2017, async/await allows us to write code sequentially, instead of nesting callbacks or chaining promises.
Internally, async/await is based on promises. In fact, then/catch and async/await are functionally equivalent.
But async/await provides a more convenient syntax to use, than nesting promises (it’s syntactic sugar to make our lives easier).
Another advantage of async/await is that it handles errors in a simpler way. With async/await, you can use the try/catch structure (which is more familiar and easier to understand for developers).
async/await Syntax
The async/await syntax is based on two keywords,
- async is placed before a function to indicate that it contains asynchronous code.
- await is placed before any operation that returns a promise to indicate that the code must wait for the promise to resolve before continuing.
Async
The async keyword is used to declare an asynchronous function. A function marked with async always returns a promise.
- If the function returns a value, the promise is resolved with that value.
- If the function throws an exception, the promise is rejected with that exception.
async function miFuncion() {
return 'Hola, mundo';
}
miFuncion().then(console.log); // 'Hola, mundo'
In the previous example, miFuncion is an asynchronous function that returns a promise resolved with the value 'Hola, mundo'.
Await
The await keyword is used inside an async function to wait for a promise to resolve.
await pauses the execution of the async function until the promise is resolved or rejected.
async function miFuncion() {
let valor = await Promise.resolve('Hola, mundo');
console.log(valor); // 'Hola, mundo'
}
miFuncion();
In this example, await is used to wait for the promise to resolve, and then the resulting value is printed.
Basic Example
Let’s see it with a simple example,
async function obtenerDatos() {
//function that simulates returning a promise
const respuesta = await FuncionQueDevuelvePromesa();
console.log(respuesta);
}
In this example,
- The
obtenerDatosfunction is asynchronous FuncionQueDevuelvePromesais a function that simulates returning a promise (it’s the response from a network request).- We use the
awaitkeyword to wait for a promise to resolve before continuing with the next line of code. - After the promise is resolved, we can do whatever we want with
respuesta.
This would be equivalent to this code, without using async and await
function obtenerDatos() {
// Call the function that returns a promise
FuncionQueDevuelvePromesa()
.then((respuesta) => {
// Handle the response when the promise resolves
console.log(respuesta);
})
.catch((error) => {
// Handle errors if the promise is rejected
console.error(error);
});
}
Which as we can see is quite a bit more of a pain 😅
Handling Errors
To handle errors in async functions, you can use try/catch instead of .catch() as you would with promises.
async function obtenerDatos() {
try {
let respuesta = await fetch('https://api.example.com/data');
if (!respuesta.ok) {
throw new Error('Error en la respuesta de la red');
}
let datos = await respuesta.json();
console.log(datos);
} catch (error) {
console.error('Error:', error);
}
}
obtenerDatos();
In this example, if an error occurs at any point inside the try block, the flow of control passes to the catch block, where the error is handled.
