How to use asynchronous initialization in a Connect middleware?
Asked Answered
H

2

7

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?

Horlacher answered 22/3, 2013 at 11:40 Comment(0)
H
2

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.

Horlacher answered 22/3, 2013 at 15:4 Comment(0)
E
0

Why you don't do like as follows,

doSomeAsyncInitialization(function () {
   //After doing all long running init process just configure your express as follows.
   app.use(<middlewares>);
   app.listen(<portnumder>);

});
Eldoria answered 22/3, 2013 at 13:18 Comment(3)
Because the initialization is only for one middleware, not for the entire app. And this pattern of course works, but it's not "nice". I dislike that everything is indented one step (and this is not just a formatting problem ;-)).Horlacher
I accept it. Since Nodejs is non-blocking, you have to do get code in long running process callback or in the way showed in your question. Ofcource, you can use some async module. Here i assumed your middleware is mandatory for all request, so that you kept in app.use() function. And my suggestion is, you just initialize middleware before start listening the port. If you are expecting more than formatting, I have to understand what is going on "doSomeAsyncInitialization" function.Eldoria
Well, as said, an idea might be that the setup function immediately returns the middleware, but that the middleware delays incoming requests until it has been fully initialized.Horlacher

© 2022 - 2024 — McMap. All rights reserved.