Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for NodeJS + Express part 5: Routes and Controllers
Eric The Coder
Eric The Coder

Posted on

     

NodeJS + Express part 5: Routes and Controllers

Here is a series of articles that will allow you to create backend applications with NodeJS + Express.

This series is the continuation of my series on the basics of NodeJS. If you don't have basic knowledge of NodeJS read this series first:Introduction to NodeJS

Node.js is today a must, so it is essential for a developer to master it.

So I will publish a new article about every two days and little by little you will learn everything there is to know about Node.js + Espress

To not miss anything follow me on twitter:https://twitter.com/EricTheCoder_


Express Router

As you seen in the previous article, creating a CRUD API with Express is easy. But you should have notice by now that all that code in the same file is bulky and we will soon lose ourself.

By convention, Express developper split code in different files and folders to optimized code organisation.

The first and most obvious thing to do is to split the route and the route implementation codes.

Here a exemple we use in the previous article

app.get('/api/products/:productID',(req,res)=>{constid=Number(req.params.productID)constproduct=products.find(product=>product.id===id)if(!product){returnres.status(404).send('Product not found')}res.json(product)})
Enter fullscreen modeExit fullscreen mode

The goal here will be to split the route and his implementation code. To do that we can use an Express Package call Router

Router help to create a list of all your apps routes and associate them to a controller file that contain the implementation code.

First step is to create a file to put all our app routes. For exemple : /routes/products.js can contain all routes related to the product resource

And next step we will create a controller file to put all our routes implementation code. For exemple: /controllers/products.js

Starting from my previous article here an exemple of a route and a controller file.

routes/products.js

constexpress=require('express')constrouter=express.Router()const{getProducts,getProduct,createProduct,updateProduct,deleteProduct}=require('../controllers/products.js')router.get('/',getProducts)router.get('/:productID',getProduct)router.post('/',createProduct)router.put('/:productID',updateProduct)router.delete('/:productID',deleteProduct)module.exports=router
Enter fullscreen modeExit fullscreen mode

As you can see the implementation is very easy and straightforward.

First create an instance to the Router object

Then import all the controller functions.

Lastly, use the router object to create a route and controller association.

Here is an exemple of the controller functions
controllers/products.js

constproducts=require('../data.js')constgetProducts=((req,res)=>{res.json(products)})constgetProduct=((req,res)=>{constid=Number(req.params.productID)constproduct=products.find(product=>product.id===id)if(!product){returnres.status(404).send('Product not found')}res.json(product)})constcreateProduct=((req,res)=>{constnewProduct={id:products.length+1,name:req.body.name,price:req.body.price}products.push(newProduct)res.status(201).json(newProduct)})constupdateProduct=((req,res)=>{constid=Number(req.params.productID)constindex=products.findIndex(product=>product.id===id)constupdatedProduct={id:products[index].id,name:req.body.name,price:req.body.price}products[index]=updatedProductres.status(200).json('Product updated')})constdeleteProduct=((req,res)=>{constid=Number(req.params.productID)constindex=products.findIndex(product=>product.id===id)products.splice(index,1)res.status(200).json('Product deleted')})module.exports={getProducts,getProduct,createProduct,updateProduct,deleteProduct}
Enter fullscreen modeExit fullscreen mode

Nothing really new here, it's the same implementation but code are now in a separate functions with a req and res parameter.

Once the routes and controllers files are created we need to tell Express to use those routes

From the main file add a app.use() with our routes reference

constexpress=require('express')constapp=express()constproducts=require('./data.js')constproducts_routes=require('./routes/products.js')app.listen(5000,()=>{console.log('server is listening on port 5000')})app.use(express.json())app.use('/api/products',products_routes)
Enter fullscreen modeExit fullscreen mode

Noted, the app.use() have routes prefix in '/api/products' that mean all url path in the routes file will include that prefix automatically.

Conclusion

That's all for today, follow me on twitter:https://twitter.com/EricTheCoder_ to be notified of the publication of the next article (within two days).

Top comments(8)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
somervilletom profile image
SomervilleTom
  • Joined

I appreciate this, simple and clear presentation.

In this approach, does input validation belong in the Router or the Controller?

Consider a query parameter that is required by a given route , such as?someRequiredField=someRequiredValue.

I'm accustomed to writing code along the lines of:

let someRequiredField;// ...if (req.query.someRequiredField !== undefined) {    artifact = req.query.someRequiredField;} else {    const http400Error = new HTTP400Error('Missing value for someRequiredField');    throw http400Error;}
Enter fullscreen modeExit fullscreen mode

This input validation is specific to the specific controller, so that's an argument for putting it in the Controller.

I hope I can find a way to make each controller an instance of an ES6 class, so that it can share common behavior inherited from a more abstract ancestor.

The API I'm working on has five controllers with 5-10 endpoints for each controller.

That's a total of something like 25-50 endpoints altogether. I'm therefore eager share as much per-endpoint boilerplate as possible.

CollapseExpand
 
vikramparihar profile image
vikram parihar
  • Location
    India
  • Work
    Software engineer @ Remote
  • Joined

Nice. You wrote this code in very good structure.

CollapseExpand
 
olsard profile image
olsard
  • Joined

Thanks for good structure example.

CollapseExpand
 
louisnelza profile image
Louis Nel
  • Joined

Very neat. I like how you split the route and controllers into separate functions. Definitely something I will do in my code going forward.

CollapseExpand
 
carlosmoliv profile image
Carlos Oliveira
  • Joined

Hey, nice article. When creating controllers in JavaScript, is it more effective to use classes or functions?

CollapseExpand
 
dlozlami profile image
UX DLOZI
  • Joined

Great resource. Thanks

CollapseExpand
 
swdrana profile image
Rana
  • Location
    Satkhira, Bangladesh.
  • Joined

thanks

CollapseExpand
 
ashlee380518 profile image
ashlee380518
  • Joined

Thank you.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Businessman and blogger #Javascript, #Python and #PHP. My favorite frameworks/librairies are #React, #Laravel, and #Django. I am also a fan of #TailwindCSS
  • Location
    Canada
  • Joined

More fromEric The Coder

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp