In JavaScript, the async/await
syntax is a modern approach to handling asynchronous operations. It provides a more concise and readable way to write asynchronous code compared to using callbacks or promises. The async
keyword is used to define an asynchronous function, while the await
keyword is used to pause the execution of the function until a promise is resolved. This section will introduce you to the async/await
syntax in JavaScript and demonstrate how it can simplify working with promises.
The general syntax for an async
function is as follows:
The async
keyword before a function declaration indicates that the function will return a promise. Inside an async
function, you can use the await
keyword to pause the execution of the function until a promise is resolved. The await
keyword can only be used inside an async
function.
The general syntax for using the await
keyword is as follows:
When the await
keyword is used, the function execution is paused until the promise is resolved. The value of the promise is stored in the result
variable, which can then be used in the subsequent code.
Let’s see an example of using async/await
to fetch data from a server:
In the example above, the fetchData
function uses the fetch
API to make a network request to https://api.example.com/data
. The await
keyword is used to pause the function execution until the promise returned by fetch
is resolved. Once the promise is resolved, the response is converted to JSON using the response.json()
method, and the data is returned.
It is common to use try/catch
blocks with async/await
to handle errors that may occur during the execution of asynchronous code. Here’s an example:
In the example above, the try
block contains the asynchronous code that may throw an error. If an error occurs during the execution of the fetchData
function, the catch
block will handle the error. You can log the error, throw a new error, or perform any other error handling logic inside the catch
block.
Let’s refactor the example from the previous section to use async/await along with promises. Here are our three functions getId
, getCourses
, and getGrades
that return promises:
Here is that code that consumes these functions:
We can refactor the code above to use async/await
as follows:
In the refactored code, the displayStudentInfo
function is defined as an async
function. Inside this function, we use await
to call the getId
, getCourses
, and getGrades
functions sequentially. The try/catch
block is used to handle any errors that may occur during the execution of these functions. Running the code should result in the same output as before.
You might be wondering why we needed to define the displayStudentInfo
function instead of directly using async/await
in the global scope. The reason is that top-level await
is not allowed in JavaScript modules. Therefore, we need to wrap the await
calls inside an async
function to use async/await
syntax.
Arguably, the async/await
syntax makes the code more readable and easier to follow compared to using promises and chaining .then
and .catch
blocks. It simplifies the process of writing asynchronous code and handling errors, making it a powerful tool for managing asynchronous operations in JavaScript. By using async/await
, you can write cleaner and more maintainable code that is easier to reason about.
To gain more practice with async/await
, we can refactor the getId
, getCourses
, and getGrades
functions to use async/await
as well. This will further demonstrate how async/await
can simplify working with promises and make the code more readable and concise.
In the refactored code, the getId
, getCourses
, and getGrades
functions are rewritten to use the async/await
syntax with the asyncWork
function that simulates network requests. The functions now directly return the resolved values instead of using promises. The displayStudentInfo
function remains the same and uses async/await
to call the refactored functions.
The async/await syntax simplifies the code by removing the need for explicit promise handling and chaining. It allows you to write asynchronous code that closely resembles synchronous code, making it easier to understand and maintain. By using async/await, you can write cleaner and more readable code that is easier to reason about and debug. It might be interesting to know that async/await is syntax sugar over promises, which means that it is built on top of promises to provide a more intuitive way to work with asynchronous code.