1

I'm building a restful web service api using NodeJS.It uses Mongoose as ODM and using MongoDB for backend. Below i will explain my scenario

I started nodejs server After that i shutdown the MongoDB database. Then call the GET api call,it doest catch any errors and api call get hang.

database config in main.js file

var mongoose = require('mongoose');
var uri = 'mongodb://localhost/mydb';
mongoose.Promise = global.Promise;
var options = { server: {socketOptions: { keepAlive: 300000, connectTimeoutMS: 10000 } } } ;
mongoose.connect(uri,options);
var db = mongoose.connection;
db.on('error',console.log.bind(console,'connection refused !!!!!'));
db.once('open', console.log.bind(console,'connection success !!!!!'));

this is my basic GET call

 var express = require('express');
    var router = express.Router();
    var mongoose = require('mongoose');
    var rootRes = require('../model/rootresources.js');

    router.get('/', function(req, res, next) {
      rootRes.find({},function (err, rootResource) {
    if (err){
     console.log('Error occurd !!!') }
    res.json(rootResource);
});
});

Even database connection failed, the code does not goes to error block. So didn't capture the database refuse when database connection is failed in the API call.

I want to capture that error and send internal server error (code:500) to client. I tried to find the solution but still could not find it Any solutions or do i made a mistake ?

Thank you Amila

2 Answers 2

1

Did you put the two parts of code in the same file(ie. main.js) or two different files.

put them in the same file, and run node main.js do throw exceptions.

// main.js
var mongoose = require('mongoose');
var uri = 'mongodb://localhost/mydb';
mongoose.Promise = global.Promise;
var options = { server: {socketOptions: { keepAlive: 300000, 
connectTimeoutMS: 10000 } } } ;
mongoose.connect(uri,options);
var db = mongoose.connection;
db.on('error',console.log.bind(console,'connection refused !!!!!'));
db.once('open', console.log.bind(console,'connection success !!!!!'));

var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var rootRes = require('../model/rootresources.js');

router.get('/', function(req, res, next) {
  rootRes.find({},function (err, rootResource) {
  if (err){
    console.log('Error occurd !!!') }
  res.json(rootResource);
  });
});

exceptions are:

connection refused !!!!! { MongoError: failed to connect to server [localhost:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]
etc...

So, I think maybe you put codes about express in a file like index.js and codes about mongoose connection in another file. And just run node index.js in command line. While running codes in index.js will not include codes in other files, codes in main.js will not be executed. As the result, there is no error info.

Updates Two ways of I know two ways of doing this:

1.In main.js create function which creates connection to database and returns a instance of db so that you can call it function in you main code.

// main.js like this
var mongoose = require('mongoose');
function createConnection(url) {
  mongoose.connect(url,options);
  var db = mongoose.connection;
  db.on('error',console.log.bind(console,'refused !!!!!'));
  db.once('open', console.log.bind(console,'success !!!!!'));
  return db;
}
// export function
module.exports = createConnection;

// in your index.js 
var createConnection = require('./main.js');
var db = createConnection(url);
// other codes here

2.Using require or vm to compile and run javascipt code. You can find vm api detail here

//main.js
var mongoose = require('mongoose');
var uri = 'mongodb://localhost/mydb';
mongoose.Promise = global.Promise;
var options = { server: {socketOptions: { keepAlive: 300000, 
connectTimeoutMS: 10000 } } } ;
mongoose.connect(uri,options);
var db = mongoose.connection;
db.on('error',console.log.bind(console,'connection refused !!!!!'));
db.once('open', console.log.bind(console,'connection success !!!!!'));

// index.js
// require will load file and execute automaticly
var scriptSrc = require('./main');
// other codes here

You can think of the second way as using eval('var mongoose = require('mongoose'); var uri = 'mongodb://localhost/mydb'; etc...)

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for clearing me. I will try to execute like that way. understood your idea.So If we want to keep separate files for web service endpoints how we can do that. When do modularize coding we need to separate database connection separately form api code
@Amila it's hard to edit codes in comment. Updates are in the answer.
Thanks for your solution. I worked out basic solution where put all the code in same .js file. first run the web service call with database up and running. that works as usual. Then i stop the mongodb instance, then execute the api call, Then it hit the error block due database refuse exception. Soon after I tried to execute again that api call, then server hang. catching the error only first time. That's wired. Have you experiencing that type of situation.
If you stop the mongodb instance, db will generate an error and call function handler. And the state of db instance will change to unconnected or something. The thing is, db.onerror will not be called if the db instance is unconnected/down/broken to mongodb. Try this code,use db instance without connection: var mongoose = require('mongoose');var db = mongoose.connection; var coll = db.collection('test'); var result = coll.findOne(); // result is undefined So, the first time error occurs, db instance is down or broken. Whatever you do with a broken db instance will not generate errors;
1

mongoose connection do not happen unless you hit a request. so its best you handle it in your first request middleware. see code insight bellow.

module.exports = function () {

return function (req, res, next) {

            mongoose.connect(URL, MONGO_OPTIONS);
            mongoose.connection
                .once('open', () => { })
                .on('error', (error) => {
                     res.status(401).json({});
                });
...

Then pass the middleware above to your router: let me know if you need more explanation

router.get('/', myMiddleware(){})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.