accessing required modules from other modules - node.js

I have a bare-bone express application, exactly the one that is created with the express command.
I have installed socket.io and attached it to my server, like this:
var app = express(),
server = http.createServer(app),
io = io.listen(server);
server.listen(8000);
Now, I also have the routes files, which is called like this:
app.get('/', routes.index);
Inside this module I have the following function:
exports.index = function(req, res){
socket.emit('news', { message: "foo" });
};
This obviously leads to a 500 reference error, because the routes file is an exportable module, and obviously has no idea what the socket is, as it is located in the app.js file.
Is there a way I can access this socket object from this, or any other file? Please note that it is attached to the express generated app. Here is a link to said project: http://jsfiddle.net/E27yN
extra: what about getting/setting session data?
Thanks in advance.

If I'm reading this correctly, I had a very similar problem: Handling Node.js Async Returns with "require" (Node ORM)
The way I resolved it was by putting a function call to the require, and returning that function in my exports, then that was accessible via that local variable. In your case, I think it'd be something like this:
var routes = require("routes.js")(io);
console.log(routes.index()); // will log return of the function "index" in routes.js.
// in routes.js
module.exports = function(io) {
var exports = this;
exports.index = function(req,res,io) {
// now io.socket is available to routes
console.log(io);
}
return exports;
}
Now you can access whatever you've exported by using that variable. So getting and setting session data would be a matter of getting that info to/from the proper place and modifying it in your parent file (usually whatever you're launching with node, like app.js or what have you).
Hope this helps!
EDIT: After discussing this in the comments, I think the problem is you're trying to use express and socket.io on the same port.
The example they give in your link (http://socket.io/#how-to-use) actually shows that they are serving up index.html from app.get("/"). Index.html includes the socket.io script file () which is by default served up when you start your socket server.
That would look like this jsfiddle: http://jsfiddle.net/Lytpx/
Note that you serve up the index.html page through express, but your socket service actually serves up /socket.io.js which then makes connection calls to the listening socket service (note, you may want to change localhost in your io.connect call in index.html to whatever your server is).

Related

Using Mixpanel - Node Library in Express

I am currently trying integrate the Mixpanel Node library into a test application that I am building. This is a Node.js application using the express framework.
As per the express docs, I have a JS file to manage the project, a folder called "public" that contains all of my static files, and another folder with the node modules that come with express.
I have two static HTML pages in "public" that I am trying to put mixpanel tracking into. I am running the project locally by running node app.js.
app.js includes:
const express = require('express');
const app = express();
const port = 3000;
const path = require('path');
//Mixpanel Additions
var Mixpanel = require('mixpanel');
var mixpanel = Mixpanel.init('<I am putting my project token here>', {
protocol: 'https'
});
//App Configuration and Init
app.use(express.static('public'));
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname + '/public/page.html'));
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
In my HTML files I try to use mixpanel functions by putting them into script tags:
<script>
mixpanel.track("event")
</script>
But when I run node app.js and view the page in my browser it says:
Uncaught ReferenceError: mixpanel is not defined
I have a pretty poor understanding of node.js, but I am imagining that I need to use app.use(), app.get(), or something along those lines to get the Mixpanel lib loaded into the app. What am I doing wrong? I also realize that my understanding of Express and Node is pretty rudimentary, so any additional knowledge is appreciated, especially if I am way off.
If you want to call mixpanel tracking functions in the browser, you should load the mixpanel library in a script tag on the browser side, as seen here:
https://developer.mixpanel.com/docs/javascript
The purpose of the node.js package is to send events from the server side, like if you wanted to log when page.html is rendered, you could do
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname + '/public/page.html'));
mixpanel.track('event')
});

Binding Routes to a main file

I am building an application using nodeJS and angularJS. I have different routes belonging to different groups. Is there a way I can mention routes belonging to different groups in seperate files and import them into main server js file and use the methods directly from the main server js file?
Can someone help me with this?
I am binding my subroutes file using require('./ subroutes.js') in the main server js file. And in the subroutes.js, I am encapuslating my routes in module.exports = function(app){
//write your routes here
}
Another important thing here is that if your subroutes needs any variables set from server.js file, then you need to include 'server.js' in subroutes.js file as below
var file = require('./server.js');
module.exports = function(app){
//write your routes
//If you need to use variables from server.js, use file.variablename wherever needed.
}
This works!

Validate my understanding on Express Routes

Actually, before I get into the question, when I do anything like
const app = express()
app is an instance of the entire express module right? Meaning, when I do app.route, route is it an Express method right or a NodeJS method, since Node has .route as well? Anyways... I just wanted to double check this.
app.route('/games')
.post(postGame)
.get(getGames);
app.route('/games/:id');
.get(getGame)
.delete(deleteGame);
Is this the same as... and if not... why would one choose one over the other?
app.get('/games');
app.post('/games');
app.get('/games/:id');
app.delete('games/:id');
Sorry, it's just been a while since I have used Express, and couldn't find anything about this specific problem. Thanks!
app is an instance of the entire express module right?
Yes, the app object is create by calling the top-level express() function exported by the Express module. That set the default http headers, render options.... and wrap the http node module:
app.listen = function listen() {
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
You can see more in the source code here (really readble)
route is it an Express method right or a NodeJS method
Route is an express object and nodeJs don't provide a routing system like express.
And for your example yes it's totally the same. They stores the handlers function in the same this._router.route

Can't load local files when using NodeJS server

I'm very new to NodeJS, and I'm currently playing around with it (and websockets), so this question might be a bit dumb. Anyway, I'm following a tutorial which has given me a simple app.js containing the following:
var fs = require('fs')
, http = require('http')
, socketio = require('socket.io');
var server = http.createServer(function(req, res) {
res.writeHead(200, { 'Content-type': 'text/html'});
res.end(fs.readFileSync(__dirname + '/index.html'));
}).listen(8080, function() {
console.log('Listening at: http://localhost:8080');
});
socketio.listen(server).on('connection', function (socket) {
socket.on('message', function (msg) {
console.log('Message Received: ', msg);
socket.broadcast.emit('message', msg);
});
});
In my index.html I'm trying to load some js and css files, but I can't seem to load them. The files are inside a js folder which is in the same directory as my app.js and index.html, and I'm trying to load them like so:
<script src="/js/script.js"></script>
If I look at the response from the request in my browser, it's returning the content of index.html.
Again, sorry if this question is silly, but I'm stuck and have no clue where to look.
Thanks!
A web server in node.js does not serve ANY files by default (unlike some other web servers). So, if you want js files to be served, you have to define a web server route that will serve them. The code you show returns index.html for all incoming requests coming into that http server so, it should be no surpise that when a request comes in for /js/script.js, your web server sends out index.html.
A typical framework to use with node.js for web serving is Express and it has express.static() that can be used to define a route that will cover all your static files or all files in a particular directory. You could, of course, code your own static file handling or find some other module to do that also. The point is that you have to write or configure some code to serve your static resource files. That is not done for you automatically by the node.js http server.
you can specify to the server in which folder to look for what
for static files such as css, images you can use
public directory, you can provide your custom directory, but it's better to use public ,same goes for views
always require
const PATH = require('path')
app.use(express.static(PATH.join(__dirname, 'public')));
for template files such as .ejs, .html, .jade use
app.set('views', PATH.join(__dirname, 'views'));

How to reload one file on Express without restarting?

I am appending a new route to a route JavaScript file with fs.appendFileSync(...), but, as Node.Js needs to be restarted to reload files, the appended route cannot be accessed. I only need to reload the file that is being appeded to.
var express = require('express');
var router = express.Router();
module.exports = router;
/* New Routes are appended here.
Example:
router.get('/bobby', function(req, res, next){
});
*/
I've already searched Stack Overflow on ways to reload files without restarting the server, but all of the questions only involve the automated reloading for development, not the real thing. I've seen the suggestions for Nodemon and Node-Supervisor already, but those say it is just for development.
This may be a dumb question, but I don't know how to solve it.
Thank you for reading.
You can use require-reload to do that. You should have a file where you import the router.js module, to which you are appending new code, that should look like:
var reload = require('require-reload')(require),
var router = reload('router.js');
Each time you append new code you should do:
try {
router = reload('router.js');
} catch (e) {
console.error("Failed to reload router.js! Error: ", e);
}
The express-route-refresh module may come in handy too. In fact, internally it also uses require-reload.

Resources