Correct sampling error handling for Mongoose?

This is a clean question from practice. I am new to Node and Mongoose. I absolutely adore the technology and provoke the project to create an API supported by JSON for the application I am creating.

I find myself constantly repeating code when I retrieve objects from my database. For example:

Playlist.findById(req.params.id, function(err,playlist){ if (err) return res.json({error: "Error fetching playlist"}); else if (!playlist) return res.json({error: "Error finding the playlist"}); //Actual code being performed on the playlist that I'm fetching }); 

The error handling at the top of the function call is annoying because I have to repeat this code for every database call ... or so I think.

I was thinking about using a callback like:

 var fetchCallback = function(err,objOrDoc,callback){ //Handle the error messages callback(objOrDoc); }; 

However, this approach would ruin my sequential thread, as I would have to define a callback function before I fetch. Therefore, if I had many database queries related to each other, I would have to place the callbacks in the reverse order, which is far from ideal in terms of pure coding.

I am wondering if anyone has run into this problem and has any recommendations for reducing recurrence.

I also use the express framework, so if there is a useful way to deal with this in express, I will also be interested to know.

+7
source share
1 answer

There are some interesting approaches you could try here.

In the simplest case, you can simply have a function that loads an object and processes the output in an error state.

 fetchResource = function(model, req, res, callback) { model.findById(req.params.id, function(err, resource) { if (err) return res.json({error: "Error fetching " + model.toString()}); else if (!playlist) return res.json({error: "Error finding the " + model.toString()}); callback(resource); }); }; app.on('/playlists/1', function(req, res) { fetchResource(Playlist, req, res, function(playlist) { // code to deal with playlist. }); }); 

This is still quite a bit of duplication, so I can try moving it to middleware .

Routing middleware

Routes can use route-specific middleware by passing one or more additional callbacks (or arrays) to the method. This feature is extremely useful for restricting access, loading data used by a route, etc.

Now I have not tested this, and it is a little waved (read: pseudocode), but I think that it should serve as a worthy example.

 // assuming a URL of '/playlist/5' or '/user/10/edit', etc. function loadResource(model) { return function(req, res, next) { model.findById(req.params.id, function(err, resource) { if (err) return res.json({error: "Error fetching " + model.toString()}); else if (!resource) return res.json({error: "Error finding the " + model.toString()}); req.resource = resource; next(); }); } } app.get('/playlist/:id', loadResource(Playlist), function(req, res) { var playlist = req.resource; ... }); app.get('/user/:id', loadResource(User), function(req, res) { var user = req.resource; ... }); 

The express source contains a pretty good example of this template , and the intermediate section in the documents (in particular, in the section "Routing middleware") describes it in detail.

+12
source

All Articles