15

I've created a nodeJS application which needs to create a server which works OK like the following in file server.js:

http.createServer(app).listen(app.get('port'), function (err) {
    if (err) {
        console.error(err);
    } else {
        runProcess();
        console.log('Server listening on port ' + app.get('port'));
    }
});

Now I need to pass this server to some file and my app built like the following:

server.js 
 app.js
  routes.js
   action.js

So I did it quick like the following,Is there a better way to do that?

This is the server.js after the changes:

var server = http.createServer(app);
app.setServer(server);
server.createServer(app).listen(app.get('port'), function (err) {
    if (err) {
        console.error(err);
    } else {
        runProcess();
        console.log('Server listening on port ' + app.get('port'));
    }
});

In the app.js I've the router file and I did like the following:

app.use('/', routes.router, function (req, res, next) {
    next();
});

app.setServer = function(http) {
    routes.setServer(http);
}

module.exports = app;

This code I put in the router.js file:

module.exports = {
    router: applicationRouters,
    setServer: function(http) {
        //here I set server to the file action.js
        action.setServer(http);
    }
}

And in the action js, I did the following:

module.exports = {
    setServer: function(http) {
...

I need to pass the http between layers and not use it as require in different file/module. How do I do that in node.js?

George Stocker
  • 57,289
  • 29
  • 176
  • 237
  • In your new server.js, you have `server.createServer(app)`. Is that a typo? – anubina Oct 05 '15 at 14:27
  • A few issues: The commenter above points out what appears to be a typo; meaning this code doesn't actually work; secondly; are you looking for 'style points' or is there a legitimate reason the 'working' approach doesn't actually work for you? – George Stocker Oct 06 '15 at 19:53
  • @GeorgeStocker - I need to pass it (the http) between layers and not using it as require in other file....any idea what is right way to do that ? –  Oct 08 '15 at 07:18
  • @GeorgeStocker - can you please remove the hold, I need help here and this is not trivial ....I want to put on it bounty which maybe can help me to progress with my problem since as you see the post was read by many pepole but only one answer which doesnt help to much... –  Oct 08 '15 at 13:41
  • @Mark Your title wasn't very clear; nor was your question. I improved both and re-opened it. Next time you ask a question pay special attention to both parts, as that can keep your question from being closed. – George Stocker Oct 08 '15 at 14:32
  • 1. Is there a (good) reason you call the server parameter `http` in all places? it just creates a lot of pointless confusion. 2. why does actions.js need the instance of the server? – Amit Oct 08 '15 at 15:39

2 Answers2

6

You don't need to pass the server to routes. Just include them prior to creating the server:

someroute.js

var router = require("express").Router();
router.use('/', routes.router, function (req, res) {
    return res.json();
});

module.exports = router;

server.js

var app = express();
....
var someroute = require("./routes/someroute");
app.use("/someroute", someroute);
server.createServer(app);

Update to the answer based on feedback:

In your server.js file you probably have a variable to hold the socket.io instance when it's initialized, let's call it io.

You will initialized the io variable like this:

//example taken from socket.io front page
var io = require('socket.io')(80); 

When registering middleware you can attach this variable to req and use it in the routes:

//this goes prior to your route registration
app.use(function(req, res, next) {
    req.io = io;
});

In the routes you will refer to req.io as a socket instance:

router.use('/', routes.router, function (req, res, next) {
    req.io.emit("something", {});
});
Vsevolod Goloviznin
  • 12,074
  • 1
  • 49
  • 50
  • Thanks but I need to pass the http between layers and not use it as require in different file/module...any idea how to do this right? –  Oct 08 '15 at 07:20
  • I need it to support WebSocket and it didnt work before I do that like I put in the post and now Its working...I wonder if there is nicer way to pass it between layers from the server to the app to the router and the action.js ??? –  Oct 08 '15 at 07:30
  • You can put socket config into another file and require it everywhere, or you can attach socket to `req` parameter in the middleware and use it in your routes like `req.io` – Vsevolod Goloviznin Oct 08 '15 at 07:38
  • Not sure that I got it can you provide it as answer please and i'll try it soon... –  Oct 08 '15 at 07:39
  • Thanks a lot Vsevolod 1+ , Currenlty Im not using the socket IO i base on node-http-proxy and my question is just how can I pass the http between layers better than I provided in my post, is there is a better way? you can just take my code and pass it from the server until the action file...Thanks! –  Oct 08 '15 at 08:00
  • @Mark than you just export your server variable in server.js and require it in the modules. – Vsevolod Goloviznin Oct 08 '15 at 08:08
  • What's the problem calling `require` each file? – Vsevolod Goloviznin Oct 08 '15 at 09:57
  • Can you please show me how should I do it from the server to the app to the route and then to the action?Thanks! –  Oct 08 '15 at 10:04
  • @Mark in fact you can take my socket.io example and just replace socket with `server` variable, should be working and probably would be the easiest way for you – Vsevolod Goloviznin Oct 08 '15 at 12:49
  • @Mark you can put `http` there – Vsevolod Goloviznin Oct 08 '15 at 14:13
  • Thanks I try it but its not working but maybe I miss something , can you please update your post with the exact code which I need to use , I put all the code in the post...and I provide bounty for this question...:) –  Oct 08 '15 at 15:05
  • HI Again, can you assist please? –  Oct 12 '15 at 09:31
  • @Mark I can't help you more unless you post your code and what do you need to accomplish with it. – Vsevolod Goloviznin Oct 12 '15 at 09:35
2

If I get you right, all you want to do is pass an instance to other modules, without having to require or re-initialize them.

server.js

module.exports = (function () {
    // create the server
    var http = require('http'),
        express = require('express'),
        app = express(),
        server = http.createServer(app);

    server.listen(80, function () {
        // require and invoke the modules that need this http/server instance here
        require('router')(server);
        require('action')(server);
    });
}());

router.js

module.exports = function (server) {
    // use server here..
};

action.js

module.exports = function (server) {
    // use server here..
};

So what you do is, first declare and initialize the object within your main module, you want to pass around. Then in the secondary modules, you just declare the module with a signature that takes this object as an argument. Finally, you'll require them only once within your main module (server.js in this case).

Note 1: I renamed the http variable to server to prevent confusion with the http built-in module.

Note 2: Don't forget to require those modules after you fully initialize the object. e.g. if this is a http server as in your example, you should better require other modules after you create the server and within the listen callback.

Note 3: Your code; after changes, does not look correct. You call var server = http.createServer() then you call server.createServer() again.

Onur Yıldırım
  • 32,327
  • 12
  • 84
  • 98
  • Thanks 1+, i'll try it soon and let you know...two question 1. your solution is not create depandency between the action and server .js file which is the starting point of the program ?2. can you please provide example to your second note ? –  Oct 09 '15 at 08:06
  • @Mark, as in your example server.js is the starting point, the main module. I've updated the example in my answer. – Onur Yıldırım Oct 09 '15 at 10:04
  • Thanks but do you think this is the right way since I've created dependency between the server and the action JS?? –  Oct 12 '15 at 09:32
  • Well, what I propose does not enforce that dependency. action.js obviously needs the `server` instance since you have a `.setServer()` method. So instead of that; this enables you to initialise the instance only once and pass it around between modules. You just invoke those modules with the `server` argument; which is more proper and elegant in my opinion. – Onur Yıldırım Oct 12 '15 at 12:52