Search code examples
node.jsexpressnode.js-connect

How to use asynchronous initialization in a Connect middleware?


I wrote a middleware for Connect and Express that requires some heavy lifting in its setup method. Due to the nature of the initialization tasks this stuff is asynchronous, so I have the problem that the middleware shall only be accessible once the initialization has been run.

Currently I have solved it using a callback:

function setupMiddleware(callback) {
  doSomeAsyncInitialization(function () {
    callback(function (req, res, next) {
      // The actual middleware goes here ...
    });
  });
}

This works, but it's not nice for the caller. Instead of being able to do:

app.use(setupMiddleware());

I have to do:

setupMiddleware(functin (middleware) {
  app.use(middleware);
});

Now I was thinking whether there is a better approach, e.g. let the middleware initialize in the background and delay all incoming requests until the middleware is ready.

How could I solve this? Any ideas or best practices that I should use here?


Solution

  • I now solved it using an isInitialized variable and delaying the middleware function itself. See the following example:

    var connect = require('connect');
    
    var setup = function () {
      var isInitialized = false;
    
      setTimeout(function () {
        isInitialized = true;
      }, 10000);
    
      function run (req, res, next) {
        res.write('Foo');
        res.end();
      }
    
      function delay (req, res, next) {
        if (isInitialized) {
          return run(req, res, next);
        }
    
        setTimeout(function () {
          delay(req, res, next);
        }, 1000);
      }
    
      return function (req, res, next) {
        if (req.url === '/foo') {
          delay(req, res, next);
          return;
        }
        next();
      }
    };
    
    var app = connect();
    app.use(setup());
    app.use(function (req, res) {
      res.write('Fertig!');
      res.end();
    });
    
    var http = require('http');
    
    http.createServer(app).listen(5000);
    

    Please note that this code has not been optimized or refactored in any way, it just is a demonstration that the idea itself works.