I have searched all over but all I find are basic ways to use socket.io.
I am trying to use socket.io in one of my routes but cant. I am using express, node.js, and jade. My issues is that i cant access io variable form app.j in other routes. Im not sure if am just supposed to call it every time. Also, when i try to requre the exported app.js modules its says that the app.j could not be found.
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();
//SOCKET/I/o
var http = require('http').Server(app);
var io = require('socket.io')(http);
var port = process.env.PORT || 3000;
//
var login = require('./routes/login');
var index = require('./routes/index');
var users = require('./routes/users');
var news = require('./routes/news');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
// TODO Not sure if this is working
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', login);
app.use('/index',index);
app.use('/users', users);
app.use('/news',news);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
/routes/login.js
var express = require('express');
var app = require('./app');
var firebase = require("firebase");
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('login');
});
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
module.exports = router;
/views/login.jade
doctype html
html
head
title login
link(rel='stylesheet', href='/stylesheets/main.css')
body
input(type="email",placeholder="email",id="userEmail")
input(type="password",placeholder="password",id="userPassword")
script(src="https://cdn.socket.io/socket.io-1.2.0.js")
script.
socket.on('connection', function (data) {
console.log(data);
socket.emit('my other event', {my: 'data'});
});
button(onclick='signin()') Sign In
button(onclick='signup()') Sign Up
As you're not running a single-page-app with html-router, the Socket.io instance is only initialised on the first route, so for every route you have to do this:
var socket = io()
socket.on('connection', function (data) {
console.log(data);
socket.emit('my other event', {my: 'data'});
});
Only then it would work.
Related
Im using node js with express framework and socket.io in my project.
when i load test page in browser(with this address: http://localhost:3001/test) every thing is fine and print "a user connected" in server log but when i refresh page again print that message two time and with another refresh print that message three times and with every refresh repeat that message.
whats wrong in my code ?
thanks.
test.js
var express = require('express');
var router = express.Router();
var io = require('../app');
router.get('/', function(req, res, next) {
io.on('connection', function(socket){
console.log('a user connected');
});
res.render('test', { title: 'test' });
});
module.exports = router;
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var session = require('express-session')
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(3001);
module.exports = io;
var index = require('./routes/index');
var users = require('./routes/users');
var test = require('./routes/test');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
app.use('/test', test);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
You are adding an additional event handler on every GET / request.
You only need to add the event handler once, outside of a http route. Think of it as the socketio equivalent of a route.
var io = require('socket.io')(server);
io.on('connection', function(socket){
console.log('a user connected');
});
Then in your router, just deal with the http request
router.get('/', function(req, res, next) {
res.render('test', { title: 'test' });
});
I am learning to use socket.io, but when I add
script(type='text/javascript', src='/socket.io/socket.io.js')
in my client, and I add code:
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.on('connection', function(socket){
console.log('------------connection');
});
in app.js, but my client do get 404 error when trying to get /socket.io/socket.io.js.
I chage my code to :
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
var server = require('http').createServer();
var io = require('socket.io').listen(server);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
var userlist = {};
io.on('connection', function(data){
console.log('------------connection');
socket.name = data.user;
if (!userlist[data.user]) {
userlist[data.user] = data.user;
};
io.emit("online", { userlist: userlist, user: data.user});
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
server.listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
module.exports = app;
and I also have the code as follow in my javascript:
$(document).ready(function() {
var socket = io.connect('http://localhost:3000');
// other code
}
My application works when i specify a port number to socket.io that is diffrent from the server port number. The working code goes as follows:
This is my app.js file:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var configDB = require('./config/database.js');
var session = require('express-session');
var passport = require('passport');
var routes = require('./routes/index');
var auth = require('./routes/auth.js');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.set(process.env.PORT || 1337);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({ secret: 'mysessionsecret' }));
app.use(passport.initialize());
app.use(passport.session());
mongoose.connect(configDB.url);
app.use('/', routes);
app.use('/auth', auth);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
var talk = require('./socket/talk.js')(app);
module.exports = app;
This is my talk.js file:
var init = function (app){
var server = require("http").createServer(app).listen(3000);
var io = require("socket.io").listen(server);
var socketioJwt = require("socketio-jwt");
var jwtSecret = require('../config/jwtSecret');
console.log("init");
io.set("authorization", socketioJwt.authorize({
secret: jwtSecret,
handshake: true
}));
io.sockets.on("connection", function (socket) {
console.log("connected");
socket.on("send", function (data) {
console.log(data);
var username = data.username;
var message = data.message;
var datetime = data.datetime;
socket.broadcast.emit("send", data);
});
socket.on("busy", function () {
socket.emit("busy");
socket.broadcast.emit("busy");
});
socket.on("free", function () {
socket.emit("free");
socket.broadcast.emit("free");
});
});
}
module.exports = init;
This is my script tag in index.ejs:
<script src="http://localhost:3000/socket.io/socket.io.js"></script>
And finally this is my io connect from the client:
socket = io("http://localhost:3000/",{
query: 'token=' + tok
});
This works but the problem is that i want to publish my site to Azure but it is not possible to let a Azure website listen to diffrent ports. At least i think it is not possible.
One of the many things I tried is changing the talk.js file to this:
var init = function (app){
var server = require("http").createServer(app).listen(app.get('port'));
var io = require("socket.io").listen(server);
...
But i it doesn't work. I always get something along the lines of http://localhost/socket.io/socket.io.js not found
If i change the script tag in my index.ejs file to this
<script src="http://cdn.socket.io/socket.io-1.2.1.js"></script>
The socket.io.js file gets loaded but when i connect form te client side i get a continious 404 not found error.
I looked at a lot of solutions online but none of them work. I really don't know what i am doing wrong.
This error comes from the bin/www.js file being called before app.js when using npm start. A quick solution is to bypass www.js, which is only used to handle some common errors, as it is suggested in this answer.
This github repo is an implementation of this solution and can be used as a starting point for any Express.js + socket.io application.
i'm using socket.io in my node project and wanted to know how to possibly export the io variable
this is what i have done so far but i get this error: Object #<Object> has no method 'on'
in app.js:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index')(io);
var users = require('./routes/user');
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(4000);
require('./routes/index')(io);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// app.use(favicon(__dirname + '/public/img/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
/// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err,
title: 'error'
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {},
title: 'error'
});
});
/*
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
*/
module.exports = app;
in index.js
var io = require('../app');
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
the reason i want export the variable is so that i dont have to define io is index.js like i did in app.js which leads to me basically defining both server and app variable !
I just want to do all my socket.io stuff in the index.js route essentially (except from having to redefine the app, server and io variables in index.js ) !
Hope i have explained my self enough
Thank you !
Your dependencies are not set up correctly. You are executing index.js before io is initialized
var routes = require('./routes/index');
/* index.js starts being executed at this point
* hence, io is undefined inside index.js
*/
Instead, why don't you try
app.js
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(4000);
module.exports = io;
var routes = require('./routes/index');
var users = require('./routes/user');
index.js
var io = require('../app');
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
I think you need to use the sockets.
io.sockets.on('connection', ... );
It looks like a circular dependency (app.js requires index.js and index.js requires app.js)
Try this.
change app.js to:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var users = require('./routes/user');
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(4000);
require('./routes/index')(io);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// app.use(favicon(__dirname + '/public/img/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/users', users);
/// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err,
title: 'error'
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {},
title: 'error'
});
});
/*
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
*/
module.exports = app;
change index.js to:
module.exports = function(io){
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
}
Use "global.io" instead of "var io" in app.js
I have created a new Express application. It generated app.js for me and I have then created the following index.js bringing in socket.io:
var app = require('./app');
server=app.listen(3000);
var io = require('socket.io');
var socket = io.listen(server, { log: false });
socket.on('connection', function (client){
console.log('socket connected!');
});
Can anyone advise how I would access socket.io within the routes files?
For reference, the default generated app.js is below:
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
/// catch 404 and forwarding to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
SocketIO does not work with routes it works with sockets.
That said you might want to use express-io instead as this specially made for this or if you are building a realtime web app then try using sailsjs which already has socketIO integrated to it.
Do this to your main app.js
app = require('express.io')()
app.http().io()
app.listen(7076)
Then on your routes do something like:
app.get('/', function(req, res) {
// Do normal req and res here
// Forward to realtime route
req.io.route('hello')
})
// This realtime route will handle the realtime request
app.io.route('hello', function(req) {
req.io.broadcast('hello visitor');
})
See the express-io documentation here.
Or you can do this if you really want to stick with express + socketio
On your app.js
server = http.createServer(app)
io = require('socket.io').listen(server)
require('.sockets')(io);
Then create a file sockets.js
module.exports = function(io) {
io.sockets.on('connection', function (socket) {
socket.on('captain', function(data) {
console.log(data);
socket.emit('Hello');
});
});
};
You can then call that to your routes/controllers.
The route:
const Router = require('express').Router
const router = new Router();
router.get('/my-route', (req, res, next) => {
console.log(req.app.locals.io) //io object
const io = req.app.locals.io
io.emit('my event', { my: 'data' }) //emit to everyone
res.send("OK")
});
module.exports = router
The main file:
const app = require('express')()
const server = require('http').Server(app);
const io = require('socket.io')(server)
const myroute = require("./route") //route file dir
app.use(myroute);
server.listen(3000, () => {
console.log('¡Usando el puerto 3000!');
});
app.locals.io = io
I think a better way to do it is to attach the Io server to response object In the first middleware .per the way express is designed the Io server will be available to your subsequent routes.
Check this link