I would like to improve my skills in Node JS. Right now I'm interested in how to cleanly separate the service and router layers of an application so I can avoid something like code duplication.
The create method of a user scheme shall serve as an example.
In UserService.Js I store the following method for this:
function createUser(req, res, next) {
let user = new User({
userID: req.body.userID,
userName: req.body.userName,
password: req.body.password,
isAdministrator: req.body.isAdministrator
});
user.save().then(function() {
res.send(user);
}).catch(err => {
console.log(err);
});
}
The following code is stored in UserRouter.Js:
router.post('/publicUser', userService.createUser)
The code works, but the separation of concerns is not respected. How do I write the create function now with a callback function ?
My attempt looks like this:
UserService.js
function createUser() {
let user = new User
return user;
}
UserRoute.js
router.post('/publicUser',function(req,res,next){
let newOne=userService.createUser()
newOne.userID=req.body.userID
newOne.userName=req.body.userName
newOne.password=req.body.password
newOne.isAdministrator=req.body.isAdministrator
newOne.save().then(function() {
res.send(newOne);
}).catch(err => {
console.log(err);
})})
It works. But does a more elegant way exist ?
Below is the code to give you an idea of implementation. You can further enhance as per the complexity and requirements.
UserRouter.Js
// import service here
router.post('/publicUser', createUser)
async function createUser(req, res, next) {
try {
const response = await UserService.createUser(req.body);
res.send(response); // Enhance 'res' object here and return as per your requirement.
} catch (error) {
// log error
res.status(500).send(''); // Enhance 'res' object here with error and statuscode and return as per your requirement.
}
}
UserService.Js
async function createUser(body) {
// check emptiness if any for body and throw proper errors.
let userModelData = UserModel.getUserInsertPayload(body);
return UserRepository.save(userModelData);
}
UserRepository.js
// all code related to persistance. This is separate layer.
async function save(user) {
// Do any enhancement you need over the payload.
return User.save(user);
}
UserModel.js
// import User here. Create a payload related to User specific requirements.
function getUserInsertPayload(body) {
return new User({
userID: req.body.userID,
userName: req.body.userName,
password: req.body.password,
isAdministrator: req.body.isAdministrator
});
}