architecture for modular socket.io in node.js - javascript

in a node.js app, let's say i have a app.js like this
var express = require('express')
var app = express();
var server = http.createServer(app);
...
module.exports = {
app:app,
server:server
}
also, there is /lib/sockets.js, where all the logic of socket.io should go in. It looks like this:
var server = require('../app.js').server;
var io = require("socket.io").listen(server);
io.sockets.on('connection', function(socket) {
socket.on('event', function(msg) {
socket.emit('news', msg});
});
});
module.exports = io;
Is it good practice to require the server from app.js here? If not, what would be a better solution? thx

Try having your sockets.js file export a function. Then require the sockets file in your app.js and pass in any relevant arguments.
In your lib/sockets.js:
module.exports = function(server){
var io = require("socket.io").listen(server);
io.sockets.on('connection', function(socket) {
socket.on('event', function(msg) {
socket.emit('news', msg);
});
});
return io;
};
And in your app.js
var express = require("express");
var app = express();
var io = require("./lib/sockets")(app);

Related

Triggering socket.io real-time notifications from Express 4 middleware

I am building a real-time notification system using socket.io. This is my server-side code at the moment:
bin/www:
var app = require('../app');
var server = http.createServer(app);
var io = app.io
io.attach(server);
server.listen(port, function(err) {
if (err) console.log(err);
console.log('Listening on port ' + port + '...');
});
app.js:
var socket_io = require('socket.io');
var express = require('express');
var app = express();
var io = socket_io();
app.io = io;
require('./config/socket')(app.io);
config/socket.js:
var User = require('../controllers/user');
module.exports = function (io) {
io.on('connection', function (socket) {
console.log('Socket.io connected');
socket.emit('connection', "Connection created.");
socket.on('send notification', function(data) {
User.createNotification(socket.request.user, data);
});
});
};
routes/index.js:
var express = require('express');
var User = require('../controllers/user');
var router = express.Router();
router.post('/order', User.order);
module.exports = router;
controllers/user.js:
var User = require('../models/user').model;
var io = require('socket.io');
module.exports = {
order: function(req, res) {
/* some create order code */
io.emit('send notification', 'Your order was successful!');
res.sendStatus(200);
}
}
I keep getting the error TypeError: io.emit is not a function whenever I try to call the route POST /send even though I am clearly initiating socket.io in my app.js and bin/www files and requiring it in controllers/user.js. All the examples I've seen online emit notifications from within this part:
io.on('connection', function (socket) {
socket.emit(event, msg);
});
but I want my notifications to be triggered from the middleware so I can send custom notifications to the user when certain events happen in the application backend.
Try the following instead:
io.on('connection', function(socket){
socket.on('xxx', function(obj){
io.emit('xxx', {xxx: xxx})
})
})
This should suppress your TypeError:.

How to create api for client from separate file using express?

I am new to nodejs,I want to handle all routes and api from app/routes.js , I have router that i am using to get and post for the client. I dont see any response from server to client with below code, Any idea ?
app.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('./app/io').initialize(server);
var ditconsumer = require('./app/consumers/ditconsumer');
ditconsumer.start(server);
server.listen(3000, function () {
console.log('Example app listening on port 3000!');
//stconsumer.start();
});
app/routes.js
var express = require('express');
var router = express.Router();
var dirDirectory = require('./app/serverfiles/ditDir');
module.exports = function(app){
router.get('/getAllFiles',function(req,res){
dirDirectory.readDirectory(function(logFiles){
res.json(logFiles);
console.log(logFiles);
});
});
//other routes..
}
so here is what you have done wrong
you have not require route app/route and use it as middleware
You must export router in app/routes.js
here is your changed code please try it and me know if it helped
var express = require('express');
var app = express();
var myroute=require('./app/routes.js');
app.use(myroute);
var server = require('http').createServer(app);
var io = require('./app/io').initialize(server);
var ditconsumer = require('./app/consumers/ditconsumer');
ditconsumer.start(server);
server.listen(3000, function () {
console.log('Example app listening on port 3000!');
//stconsumer.start();
});
app/routes.js
var express = require('express');
var router = express.Router();
var dirDirectory = require('./app/serverfiles/ditDir');
router.get('/getAllFiles',function(req,res){
dirDirectory.readDirectory(function(logFiles){
res.json(logFiles);
console.log(logFiles);
});
});
module.exports=router;
//other routes..
}
please do let me know if this solves your problem

Socket.io setup causes hundreds of transport polling GET requests

I'm using express.js server-side and I followed the socket.io setup guide. Unfortunately the socket connection is never successful, and I receive an unruly amount of GET requests that look like this:
Here's my setup:
CLIENT - index.html
<script src="https://cdn.socket.io/socket.io-1.3.7.js"></script>
<script>
// var socket = io.connect('http://localhost');
var socket = io.connect('http://localhost:9000/');
socket.on('connected', function (serverData) {
console.log(serverData);
});
</script>
SERVER - /io/index.js
'use strict';
var socketio = require('socket.io');
var io = null;
module.exports = function(server) {
if (io) return io;
io = socketio(server);
io.on('connection', function(socket) {
console.log('Sockets connected!');
socket.emit('connected', 'Sockets connected!')
})
return io;
};
SERVER - app.js
'use strict';
// Set default node environment to development
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
var express = require('express');
var mongoose = require('mongoose');
var config = require('./config/environment');
// Connect to MongoDB
mongoose.connect(config.mongo.uri, config.mongo.options);
mongoose.connection.on('error', function(err) {
console.error('MongoDB connection error: ' + err);
process.exit(-1);
});
// Populate databases with sample data
if (config.seedDB) { require('./config/seed'); }
// Setup server
var app = express();
var server = require('http').createServer(app);
require('./config/express')(app);
require('./routes')(app);
// Setup sockets
require('./io')(server);
// Start server
function startServer() {
server.listen(config.port, config.ip, function() {
console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));
});
}
setImmediate(startServer);
// Expose app
exports = module.exports = {
app: app,
server: server
}
This is tipically what happen, when client does not reach the server.
The client try again and again . . .
For that you have to check your config server-side, checking the port and the path is often the first things you should check.
In your case, maybe you should check this part :
//require('./io')(server); typo error ??
require('./io/index.js')(server);
More further you don't seem to give the good part :
( maybe depending on version you use)
// Setup server
var app = express();
var server = require('http').createServer(app);
require('./config/express')(app);
require('./routes')(app);
// Setup sockets
require('./io')(server);
I think it should be :
// Setup server
var app = express();
var server = require('http').createServer(app);
require('./config/express')(app);
require('./routes')(app);
// Setup sockets
//require('./io')(server); |O----------------------------------|
require('./io/index.js')(app);//<---we pass app as argument----|
I hope this will help you.

how to integrate signalmaster to already existing expressjs server

I'm trying to use simplewebrtc in my app, I already have a simple nodejs server with express web framework. But to use simpleWebrtc we have to install signal master. I'm looking at the source code for the server.js file in the signal master package but I can't figure out how to combine this server.js with my already existing app.js file. This is basically my app.js
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var mongoose = require('mongoose');
var favicon = require('serve-favicon');
var bodyParser = require('body-parser');
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
console.log("connected to index");
});
and this is server.js of signalMaster
/*global console*/
var yetify = require('yetify'),
config = require('getconfig'),
uuid = require('node-uuid'),
crypto = require('crypto'),
fs = require('fs'),
port = parseInt(process.env.PORT || config.server.port, 10),
server_handler = function (req, res) {
res.writeHead(404);
res.end();
},
server = null;
// Create an http(s) server instance to that socket.io can listen to
if (config.server.secure) {
server = require('https').Server({
key: fs.readFileSync(config.server.key),
cert: fs.readFileSync(config.server.cert),
passphrase: config.server.password
}, server_handler);
} else {
server = require('http').Server(server_handler);
}
server.listen(port);
var io = require('socket.io').listen(server);
if (config.logLevel) {
// https://github.com/Automattic/socket.io/wiki/Configuring-Socket.IO
io.set('log level', config.logLevel);
}
etc, etc you can look at the rest by downloading the zip. I thought it would be just replacing server with http, but the server=null doesn't really make sense. All the dependencies are in the directory of the signalMaster unzipped file. I was reading about signalMaster here.
You will need something like this
var os = require('os');
var static = require('node-static');
var http = require('http');
var socketIO = require('socket.io');
var fileServer = new(static.Server)();
var app = http.createServer(function (req, res) {
fileServer.serve(req, res);
}).listen(2013);
var io = socketIO.listen(app);
io.sockets.on('connection', function (socket){
...
socket.on('join', function (message) {
...
}
...
}
i hope this help u

Modularizing Socket.io with Express 4

I'm trying to modularize my application files and I'm having problems with Socket.io. I would like to use the io inside my routes.js. Something like this:
var router = require('express').Router();
var io = require('./sockets/my-io');
router.get('/', function(req, res) {
io.emit('request-detected');
});
module.exports = router;
But I can't do, because the socket.io needs the app server, and when I'm inside the routes.js file, the app server is not listening or being exported yet.
Can you give me a solution, or any other approach to this problem?
Here's what I have, and if it's possible, I would like to keep the file structure:
app.js
var app = require('express')();
var routes = require('./routes');
/* ... */
app.use('/contacts', routes);
module.exports = app;
bin/www
#!/usr/bin/env node
var app = require('../wallet');
var server = app.listen(port, function() {
debug('Express is listening o port ' + port);
});
routes.js
var router = require('express').Router();
router.get('/', function(req, res) {
console.log('hey');
});
module.exports = router;
You can do it by passing the io variable to your routes module.
bin/www
#!/usr/bin/env node
var app = require('./app');
var server = app.listen(3000, function() {
console.log('Express is listening on port 3000');
}); // start the server
var socket = require('./socket')(server); // require socket.io code
var routes = require('./routes')(socket); // require routes
app.use('/', routes);
app.js
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.set('views engine', 'ejs');
app.set('views', __dirname + '/');
module.exports = app;
socket.js
var socketio = require('socket.io');
function init(server) {
var io = socketio(server);
io.on('connection', function (socket) {
console.log("socket connected");
socket.on('newEvent', function (data) {
console.log(data);
});
});
return io;
}
module.exports = init;
routes.js
var express = require('express');
var route = express.Router();
function init(io) {
route.get('/', function (req, res) {
res.render('index.ejs', {});
setTimeout(function() {io.emit('newEvent', {message: "Hi from the server"})}, 2000);
});
return route;
}
module.exports = init;
The code above worked for me. However, I'm not sure why you want to do that.
Inside the router, you still have full control of what you want to send to the user via html, so you can just add the data to the html directly.
The idea of socket.io is that you can send data between the client and back once he has loaded the html and established a connection to your server with socket.io.
As you can see in the routes.js, I had to add a timeout to the emit. This is because the socket event will be emit before the browser has reloaded the page. In my case the browser logged the event and then immediately refreshed, losing the data you just sent.
Another problem is that you don't know anything about the socket of the client that is requesting the page because he hasn't connected yet. This means that calling io.emit() will send the event to all connected sockets.
As I said, this really depends on what exactly you want to do.
EDIT:
Instead of updating your contacts using ajax, you can do that with socket.io.
socket.js
var socketio = require('socket.io');
function init(server) {
var io = socketio(server);
io.on('connection', function (socket) {
console.log("socket connected");
socket.on('newContact', function (data, callback) {
// add data.contactName to db
// after adding something, you use the callback to
// send the added data back to the client
// callback(newContact);
});
});
return io;
}
module.exports = init;
index.html
<script type="text/javascript" >
var socket = io();
// call this emit when the user wants to add a contact
socket.emit('newContact', {contactName: name}, function(newContact) {
// here you will get the result from the server and you can
// update the html with jquery for example
});
</script>
If i understand your question correctly ,maybe you can try this way.
in your routes.js file
var app = require('./app');
var server = require('http').createServer(app);
var io = require('./sockets/my-io')(server);
var route = app.Router();
in your app.js file
var port = process.env.PORT || 3000;
app.listen(port,function(){
console.log('server on port ' + port)
})

Categories

Resources