4

I wrote my own middleware as module for my purposes that looks like the following:

-- myMiddleware.js

module.exports = {
    fn1: function (req, res, next) {
       console.log('fn1');
       next();
    },

    fn2: function (req, res, next) {
        console.log('fn2');
        this.fn1(req, res, function () {
             next();
        });
    }
};

In my sserver.js I use this middleware as the following:

app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));

app.use(require('./myMiddleware').fn2);

Unfortunately that does not work because this context in fn2 in not myMiddleware.js object. How can use proper this?

BenMorel
  • 30,280
  • 40
  • 163
  • 285
Erik
  • 11,695
  • 42
  • 119
  • 194

2 Answers2

8

This is not because middlewares.
Always when a function is passed as an arguments in javascript it's losing the context. Express pass the middlewares around as an arguments. So that's why.

There are several techniques to bind the context, You can use apply, call, a closure, or the easier new ES6 arrow functions. This is an example using a closure:
[edit] fixing typos from your example, and adding functional code example.

middle.js

module.exports = {
    fn1: function(req, res, next) {
       console.log('fn1');
       next();
    },

    fn2: function(req, res, next) {
        var self = this;
        return function (req, res, next) {
            console.log('fn2');
            self.fn1(req, res, function () {
                next();
            });
        }
     }
};

sever.js (notice the fn2() )

var express = require('express');
var app = express();
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));

app.use(require('./middle.js').fn2());
app.get('/', function(req, res) {
    res.send('hey!');
});
app.listen('3000');

Googling for "javascritp function bind context" you can find good articles and understand better this behaviour.

alfonsodev
  • 2,609
  • 1
  • 21
  • 29
1

You can't, the 'this' property will always be the vanilla Server (http.Server) instance or compatible handler.

You can do this:

var middlewares = {};

module.exports = middlewares;

middlewares.fn1 = function(req, res, next){ ... };

middlewares.fn2 = function(req, res, next){ 
    middlewares.fn1(req, res, next); 
};
Alfonso de la Osa
  • 1,544
  • 1
  • 14
  • 18
  • Why can't I use just var middlewares = module.exports = {}; ? – Erik Aug 29 '13 at 12:17
  • you can!, you can also skip the middlewares reference and use exports.fn1 = ...; exports.fn2 = function(...){exports.fn1();}; that depends on how you feel more confortable. – Alfonso de la Osa Aug 30 '13 at 10:09