Question

Lets say I have the following Express/Connect middleware:

    return function(req, res, next) {
        mongoose.connect(url, options);
        var Config = mongoose.model('Config', mongoose.Schema({
            field1: Boolean,
            field2: []
        }));

        Config.findOne({}, function (err, doc) {
                    if(!err) {
                       if(someCondition)
                        // some logic: send response and interrupt middleware chain
                        res.end('Some response');
                        else
                        next();
                    }
        }
};

The issue is that database call is asynchronous. So middleware function exits before any logic executed. The task is simple: read the configuration from mongoDB and if some field value = 'something" send response, otherwise - continue middleware chain.

So, I have 2 questions at the moment:

  1. Is there any way to make asynchronous calls inside middleware?
  2. If not, is there any workaround? (AFAIK, there is no way to execute db call synchronously)
Was it helpful?

Solution

So middleware function exits before any logic executed.

Yes, but this is totally normal and 100% OK for node.js asynchronous code. That's how asynchronous code works. When the DB call completes, control flow resumes and you can either send a response or call next() at that time. This is fine.

Is there any way to make asynchronous calls inside middleware?

Yes, and the way you are doing it is fine (minus some minor caveats listed below).

If not, is there any workaround?

No workaround necessary. This is how node.js works by design. All network I/O in node.js is asynchronous.

A few minor notes

  • Make sure you either send a response OR call next() in every possible branch of your database callback function logic: error, someCondition is true, and someCondition is false. If any of your logic can end up in a branch that doesn't respond to the request and doesn't call next() the request will just hang until it fails due to a timeout. Your snippet above is missing error handling, which you need to do.
  • Move your mongoose connect call to application startup time. Don't connect on each request.
  • Move your mongoose model definition out to a separate module Config.js
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top