Thursday, January 31, 2013

expressjs async middlewares

Dealing with async Middlewares in connect/expressjs can lead to unexpected behaviors if you don't take extra precautions.


Example:

var app = express();

app.use(function (next_middleware) {
  db.query(function(error, doc) {
    /* do something with error and doc */

    next_middleware(); // 
  });
});

/* Other middlewares... */


This code could suffer from one problem. During the async db.query(), nobody will receive the emitted request events ("data" or "end" mostly) that could take place. To circumvent this issue, we could use the "pause" module by TJ Holowaychuk which saves the stream's emitted "data" and "end" events and replay them on resume(). The refactored code would look something like this:

var app = express();

app.use(function (next_middleware) {
  var pause = require('pause')(req); // Pause the receiving of events for req

  db.query(function(error, doc) {
    /* do something with error and doc */

    next_middleware();
    pause.resume(); // Replay events
  });
});

/* Other middlewares... */


It is worth to note that connect/expressjs use it internally for example in the static middleware.

Cheers.


No comments:

Post a Comment