Exercise - Read and write
The online retailer is impressed with your first web application. Now it wants you to create an API that you can read and write from. The data might be stored in a database and might contain millions of records. For that reason, the retailer wants to see an app that uses techniques that limit how much data is asked for.
Implement support to read and write data
It's common to construct an API with a number of resources. Each resource can have several operations available on it to read and write. Organizing by resource and by operations like read/write is called create, read, update, delete (CRUD). Implement the CRUD API on the products resource:
Clone the node-essentials repo by running the following command.
Note
If you completed this step in the earlier exercise, you don't need to do it again.
git clone https://github.com/MicrosoftDocs/node-essentialsThis starter project contains the product files and some starter application code. All you need to do is to fill in the missing parts.
To inspect the repo that you cloned and go to the files that you need, run this command:
cd node-essentials/nodejs-http/exercise-express-routing/reading-writingThe outline of the directory should look like this:
-| app.js -| client-get.js -| client-post.js -| client-put.js -| client-delete.js -| client-delete-route.js -| package.jsonThe package.json file contains an
expressdependency. In the terminal, run the following command to install it:npm installnpmreads from thedependenciessection in package.json.Open app.js to inspect it. The file should look like this:
const express = require('express') const app = express() const port = 3000 let bodyParser = require('body-parser'); app.use(bodyParser.json()); let products = []; app.post('/products', function(req, res) { // implement }); app.put('/products', function(req, res) { // implement }); app.delete('/products/:id', function(req, res) { // implement }); app.get('/products', (req, res) => { // implement }) app.listen(port, () => console.log(`Example app listening on port ${port}!`));The app.js file shows a skeleton of a program. Your next job is to implement the routes.
Implement routes
To implement routes, add a little code and then test it. Do this method by method until you have a fully functional API.
Support reading from the API. Locate the part of the code that looks like this:
app.get('/products', (req, res) => { // implement })Replace it with this code:
app.get('/products', (req, res) => { res.json(products); })To check that the code works, start the API by running this command:
node app.jsIn a separate terminal, run this command:
node client-get.jsYou should get the following output:
Received data [] Connection closed
The API responds with an empty array because you haven't written any data to it yet. Let's change that next.
Implement writing
To implement writing, locate this code:
app.post('/products', function(req, res) { // implement });Replace it with this code:
app.post('/products', function(req, res) { const newProduct = { ...req.body, id: products.length + 1 } products = [ ...products, newProduct] res.json(newProduct); });The new code reads incoming data from
req.bodyand constructs a JavaScript object from it. Next, it's added to theproductsarray. Finally, the new product is returned to the user.To test the code, run the server program by running this command:
node app.jsIn a separate terminal, run this command:
node client-post.jsYou should see an output like this:
response {"name":"product","id":1} Closed connectionTo check that the data is written to the API, run the following command:
node client-get.jsYou should see the following output:
Received data [{"name":"product","id":1}] Connection closedThe response tells you that when you ran client-post.js, you wrote data to the API. Also, you ran client-get.js to query the API for data. The API responded with the data that you just wrote to it.
Implement the ability to update data
To implement the ability to update your data, locate the code that looks like this:
app.put('/products', function(req, res) {});Replace it with this code:
app.put('/products', function(req, res) { let updatedProduct; products = products.map(p => { if (p.id === req.body.id) { updatedProduct = { ...p, ...req.body }; return updatedProduct; } return p; }) res.json(updatedProduct); });The new code locates the record in the
productsarray that matches theidproperty, and it updates that record.To test the code, start the server application:
node app.jsIn the other terminal, run this command to create a record:
node client-post.jsRun this command to update the newly created record:
node client-put.jsYou should see the following update in the terminal:
response {"name":"product-updated","id":1} Closed connectionTo check that the update works, run this command:
node client-get.jsYou should see this update:
Received data [{"name":"product-updated","id":1}] Connection closed
Implement deleting
To implement deleting, locate the code that looks like this:
app.delete('/products/:id', function(req, res) {});Replace it with this code:
app.delete('/products/:id', function(req, res) { const deletedProduct = products.find(p => p.id === +req.params.id); products = products.filter(p => p.id !== +req.params.id); res.json(deletedProduct); });The new code finds the product item to be deleted. Then it filters out that item from the
productsarray and responds with a filtered version ofproducts.To test the code, start the server application:
node app.jsIn a separate terminal, run this command to create a record:
node client-post.jsRun this command to remove the record:
node client-delete.jsYou should see the following output:
Received data {"name":"product","id":1} Connection closedTo check the code, run this command:
node client-get.jsIt should give this output:
Received data [] Connection closedCongratulations! You've implemented a
productsresource by using a full CRUD.
Implement CRUD
Implementing CRUD for a resource is a common task. Express has a route() method just for this purpose. When you use the route() method, your code is grouped so that it's easier to read.
To implement CRUD, replace the code in app.js with this code:
const express = require('express') const app = express() const port = 3000 let bodyParser = require('body-parser'); app.use(bodyParser.json()); let products = []; app.route('/products') .get((req, res) => { res.json(products); }) .post((req, res) => { const newProduct = { ...req.body, id: products.length + 1 } products = [...products, newProduct] res.json(newProduct); }) .put((req, res) => { let updatedProduct; products = products.map(p => { if (p.id === req.body.id) { updatedProduct = { ...p, ...req.body }; return updatedProduct; } return p; }) res.json(updatedProduct); }) .delete((req, res) => { const deletedProduct = products.find(p => p.id === +req.body.id); products = products.filter(p => p.id !== +req.body.id); res.json(deletedProduct); }) app.listen(port, () => console.log(`Example app listening on port ${port}!`))To test this new implementation, restart the server by running this command:
node app.jsIn a separate terminal window, run this command:
node client-post.jsRun this command to delete the record:
node client-delete-route.jsTo check that the record is removed, run this command:
node client-get.jsYou should see the following output:
Received data [] Connection closed
You used client-delete-route.js instead of client-delete.js in the previous exercise. The difference lies in how the route is implemented. The first version of app.js relies on deletions being done toward a route like /products/<id>, with the unique identifier being sent as a route parameter.
When you use the route() method, it implements the deletion route differently. It wants you to send unique identifier through the body instead of as a route parameter. There's no right or wrong way to implement a deletion route.
Trebate pomoć? Pogledajte naš vodič za rješavanje problema ili pošaljite željene povratne informacije prijavljivanjem problema.