开发者

How to create my own module of functions in a node.js app

I'm building my node.js app which has the following structure:

  • server.js
  • controllers/user.js

server.js require the user.js controller with:

require('./controllers/user.js').route(app, mongoose);

the controller/user.开发者_运维知识库js file is like:

function route(app, mongoose){
   function route(app, mongoose){

   // Create new User item
   app.post('/user/create', function(req, res){
     ...
   }

   // Edit user
   app.put('/user/:id/edit', function(req, res){
    ...
   }

   ...
}
module.exports.route = route;

This is working fine. I know want to had middleware in the Edit user function for instance so it looks like:

...
app.put('/user/:id/edit', loadUser, function(req, res){
...

If I define loadUser function right above this line it's working fine. When I add all the middleware fonction in a file './lib/middleware.js' and when I try to load that file in user.js with:

require('../lib/middleware.js').create(); // Create is the exported function

this does not work and I have the error message saying that loadUser is an unknow function.

Any idea ?

** UPDATE **

I have updated the files such that, in server.js (main file) I have:

...
var middleware = require('./lib/middleware.js');
...
require('./controllers/user.js').route(app, mongoose, middleware);
...

In middleware.js, I then have:

function create() {
  function loadUser(req, res, next) {
    // You would fetch your user from the db
    var user = users[req.params.id];
    if (user) {
      req.user = user;
      next();
    } else {
      next(new Error('Failed to load user ' + req.params.id));
    }
  }
return module;
}

In controllers/user.js I have

function route(app, mongoose, middleware){
   ...
   // Modify an user
   app.put('/user/edit', middleware.loadUser, function(req, res){
     ...
   }
   ...
}

When I run the app (node server.js) I then have the following error:

Error: PUT route /user/edit requires a callback

I am not sure to return the correct thing within middleware.js, not really familiar with module stuff yet. I also tried the "module.exports.create = create;" but same thing.

UPDATE WITH ANOTHER TRY

what if I create a module for the function ? In ./lib/middleware.js I would have:

(function(){
  var middleware = {};
  middleware.loadUser = function () {
  console.log("loadUser");
  }
  return middleware;
}());

And in server, I call it:

var middleware = require('./lib/middleware.js');
middleware.loadUser;

It seems to me that should work but it does not...


"global" scope in a file is actually module scope. Just by creating a function in a different file it does become in scope in your original file.

What you want to do instead is

// routes.js
var middleware = require("../lib/middleware.js").create();

app.put('/user/:id/edit', middelware["loadUser"], function(req, res){

You will find that global variables actually write to module in their scope.

Then your function loadUser() { ... } should exist in the module property.

// middleware.js
function create() { 
    ...

    return module;
}

If you return module from your create function your returning global scope.

[Edit]

function create() {
  function loadUser(req, res, next) {
    // You would fetch your user from the db
    var user = users[req.params.id];
    if (user) {
      req.user = user;
      next();
    } else {
      next(new Error('Failed to load user ' + req.params.id));
    }
  }
return module;
}

You either need to add module.loadUser = loadUser or define loadUser in module scope. I.e. outside the create function.

[Further Edit]:

A standard setup would be something like:

// middleware.js
(function() {

    function loadUser(...) {
        ...
    }

    ...

    module.exports.loadUser = loadUser;

})();

//otherfile.js
var middle = require("middleware");
middle.loadUser();


When code is loaded using require() it doesn't put anything into the global context. You have to bind it to a variable.

For example when you require your middleware file, you are able to call create() only because the module.exports object is returned from the require() function and you are able to access the call site directly. Here is how you would keep a reference to the require()d code so you could access it later:

var middleware = require('../lib/middleware.js');
middleware.create();

and probably this is what you want:

app.put('/user/:id/edit', middleware.loadUser, function(req, res) ...

update: As raynos pointed out, no function wrapper is advised in this case. See his comment.

Note that I wrapped the loadUser function reference in an anonymous function. Leaving the code as you had it would have worked as long as your code didn't rely on the value of 'this' internally.

update: I think I misunderstood what you were trying to do with create(). The above works if you define your loadUser() function as directly part of the module. If you need to do something else tricky in your Create() function you can use what I wrote above by doing something like

var loadUser = middleware.create();

Then you'll have the loadUser function defined in scope.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜