We often need to implement some asynchronous operations in an API. As we learnt earlier on, the common choices for implementing asynchronous logics are:
- callbacks
- promises
- async/await
In this section, we are going to learn how to use async/await feature to make async code easier to manage.
Note: async/await feature is supported by Node since version 7.6.0. If you are using an older version of Node, you cannot use it without transpilers like Babel.
To play with the examples in this workshop, you need to clone a project from our course's github repository:
git clone https://github.com/thoughtworks-jumpstart/express-playground.git
After you clone the project, get into the project directory, and run
npm install
Take a look at the sample codes in async_await_example.js
.
The usage of async/await is straight-forward. The only thing we need to highlight is how to handle the errors that may throw from the async functions.
Remember, the async/await function always implicitly returns a Promise. If there are any error happens within that function, someone needs to call the catch
function on the returned promise and handle the potential error.
That's why we declare the wrapAsync
helper function to handle this error scenario.
const wrapAsync = fn => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(err => next(err));
};
This function takes an async function as argument, and invoke it with the request/response. If there are any error happens, the error would be passed to catch
function and eventually passed to next
function.
Remember, once next
is called with an argument, Express Framework would treat the argument as an error and trigger the error handling flow.
This function is re-usable, and we can use it to wrap any async/await function. Actually, someone has already created an npm module for this purpose: express-async-wrap
To see this example in action, run
node async_await_example.js
If you send a request to http://localhost:3000/users/gordon, you should see a successful response. If you send a request to http://localhost:3000/posts/1, you should see error returned from server side.
In all the previous labs we have been developing synchronous code in our songs route handlers.
This is not ideal as synchronous code is blocking. eg: when if we connect to a DB or other I/O task like reading a file from disk, synchronous code blocks other requests until it has completed its execution of the task. This will slow down the performance of your server.
In this lab you will need to refactor your code to be asynchronous so that while there is an I/O operation ongoing, Express can still handle other requests.
To simulate a real DB access using Mongoose we have refactored the code which reads or writes data to the songs array, into functions which return promises that only execute after a delay of 10 milisec.
- getSongs()
- createSong()
- getSong()
- updateSong()
- deleteSong()
Your task is to refactor the 5 route handlers to use async and await together with these functions to access the songs array.
Note:
- Remember to run your tests to ensure that your API still works correctly after the refactoring
- You can choose to either use the
wrapAsync
function as shown in example above OR to wrap the code in your route handler with a try/catch like shown below. Both styles are equivalent.
router.get('/', async (req, res, next) => {
try{
let songs = await getSongs()
//success logic here
}
catch(error){
//error logic here
}
});
- Navigate to the express-songs-api project folder
- Ensure that the work from your previous lab is already commited
- checkout to branch
13-add-async
to get started
git checkout 13-add-async
-
After you have completed Lab 7, please commit all your work.
-
You may optionally install the plugin Git History Diff for viewing the difference between git branches. This will allow you to easily compare your work with the sample solution
-
https://marketplace.visualstudio.com/items?itemName=huizhou.githd
-
Next checkout to the solution branch and we will now walk through the sample solution
git checkout 14-add-async-solution
-
To view the difference between your work and the sample solution go to the VS Code file explorer, right click your folder and select
GitHD: View Folder Diff
and select compare with13-add-async
branch -
The diff sidebar will popup and you can click on the files to view the difference between your work and the sample solution.
-
When viewing the diff you can temporarily toggle the sidebar with
cmd + B
to hide it.