Asynchronous socket.io module sharing among different files and scripts - javascript

I have laid out my project to look like the following
io.js
var io = require('socket.io')();
var socketioJwt = require('socketio-jwt');
var jwtSecret = require('./settings').jwtSecret;
io.set('authorization', socketioJwt.authorize({
secret: jwtSecret,
handshake: true
}));
io.on('connection', function(socket) {
});
module.exports = io;
app,js
var io = require('./io');
...
var server = http.createServer(app);
io.attach(server);
server.listen(33666);
Now I want to use the sockets in another script in order to send messages to the connected users like so:
script.js
var io = require('./io');
...
io.emit(event, msg);
My problem is that when I log io.sockets.connected inside script.js it always returns as an empty object. I have narrowed down my problem, and I believe this is happening because when requiring the io module inside script.js, io.js is running again and therefore I am instantiating a new io object.
Any idea how can I overcome that problem?
Thanks.

Your app.js file is the one that initializes your socket server, therefore you have to require it in script.js file:
var io = require('./io');
require('./app');
...
io.emit(event, msg);
BTW, node caches all requires, so you suspicion about node "running again" your io.js file is actually not true - the only thing that the second call to require('./io') does is returning your io instances reference.

Related

How do I fix socketio spamming polling when I start my web app? [javascript, expressjs, socketio]

Here is the problem. When I load the page in the browser and check to see if my "test" was emitted, I run into this wall of spamming polling.
The code I use is exactly the same as in other projects I have done, so it makes no sense to me that this doesn't work now. -_-
app.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 8000;
server.listen(port, function(){
console.log('server ready - listening on *:8000');
});
app.get( '/*' , function( req, res, next ) {
//This is the current file they have requested
var file = req.params[0];
//Send the requesting client the file.
res.sendFile( __dirname + '/' + file );
});
io.on('connection', function (socket) {
socket.on('test', function(){
console.log("test worked");
});
});
client.js
var socket = io();
socket.emit("test");
I broke the code down to what you see above. There's nothing else. And it doesn't work. internal screaming
I'll post my comment as an answer so you can wrap up this question. One common reason that socket.io will loop with http requests and never successfully connect is if you are running mismatched version on the client and server. This seems to have happened recently with socket.io upon a recent version change so they must have made some change in how the connection logic works that makes it fail to connect if versions are mismatched.
If you load your client via this:
<script src="/socket.io/socket.io.js"></script>
Then, the client will always match the server version as long as you don't have any other <script> tags that are loading some other version of socket.io.
One more solution which worked for me ( Socket.IO 2.3.0 and Socket.IO Client 2.3.0 ) is to set the transports field when you create the instance of io on back-end and socket on front-end , like this :
On back-end :
io = require('socket.io')(http,{
log: false,
agent: false,
origins : '*:*' , // this is for the CORS browser error , I also use the cors npm module here
transports : [ 'websocket' ]
});
And on front-end :
const socket = socketIOClient(url,{
forceNew : false ,
secure : true ,
transports: [ 'websocket' ]
});
Hope it helps , if not the question owner , then maybe the others :)

How can I emit Socket.io events from a router file?

I am working on a socket.io project in which I need to emit an event when the / page is requested. But all my routings are in a separate file router/index.js. Now, I want to emit a socket event on the page request from the router file.
I can't find a way to sort this out. Can anyone help?
put your socket object in separate file and export it.
//let io.js
var http = require('http').Server(app);
var io = require('socket.io')(http);
module.export.io = io;
now in route/index.js;
var io = require('io.js')
app.get('/', function(req, res){
io.sockets.emit('home.accessed');
})
simlarly if socket code was in server.js
require it from io.js likewise.

Unresolved function or method on()

This code runs in the server. I am making a simple websocket on the server and it looks for connections made to it. However, IntelliJ does not recognize the on() method that has been called on io. I am using IntelliJ latest version and coding in Node.js
var http = require('http');
var express = require('express');
var socket = require('socket.io');
function onRequest(req,res)
{
console.log('User requested for page: ',req.url);
}
// create a middleware application
var app = express();
app.use(onRequest);
// serve static files
app.use(express.static('public'));
var server = http.createServer(app).listen(4000);
// setup the socket on the server
var io = socket(server);
io.on('connection',function(socket)
{
console.log('Socket id is: ',socket.id);
});
Try npm install #types/socket.io. It will add the necessary definition file.

Socket io instance/middleware in express

var http = require("http").Server(express);
var io = require("socket.io")(http);
server.listen(8080);
Above code work if I put in different route. But how to create an instance of it so that I don't have to declare many times?
you are not clear with your question but i think you want to you io object in different files
you can do this using
app.all("*",function(req,res,next){
req.io=io;
next();
});
define this middleware before the routing in you server file
and where you want to use this you can get this object as
function(req,res,next){
var io = req.io;
}

Socket.io client ignoring port when namespace used [Bug?]

I have a simple node.js app with socket.io (1.3.5), taken from socket.io examples:
// Setup basic express server
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 3000;
server.listen(port, function () {
console.log('Server listening at port %d', port);
});
// Routing
app.use(express.static(__dirname + '/public'));
io.of('/admin').on('connection', function(socket){
//handle conection on /admin namespace
});
io.of('/user').on('connection', function(socket){
//handle conection on /user namespace
});
Now in my front-end I connect to these specific namespaces like so (again, taken from the example):
var admin_socket = io('/admin');
var user_socket = io('/user');
The app is running on port 3000 and the website is opened using URL localhost:3000.
When doing that I am getting CORS errors, it seems like Socket.io on client side is not auto-detecting the port number as soon as I start using namespaces (in firefox dev tools I can see requests going to localhost/ rather than localhost:3000/).
If on my server-side I don't use namespaces:
io.on('connection', function(socket){
//handle general conection
});
And on front-end I connect this way:
var socket = io();
Everything works fine, port auto-discovery works and in firefox dev tools I can see connections being made to localhost:3000/.
Alternatively, if I still use namespaces on my back-end, and on front end I connect like so:
var admin_socket = io('localhost:3000/admin');
var user_socket = io(':3000/user'); //I can skip localhost
Again everything works (and indeed in firefox dev tools I can see network requests going to localhost:3000/).
How come the port auto-discovery is not working with namespaces? Is there a way to get it to work? Am I missing something here? Thanks.
See my answer below for a fix...
Ok so I did some debugging of code in socket.io.js and realized there is a potential bug there. On line 1050 a loc.hostname is used instead of loc.host.
This causes a hostname to be used when passing in a namespace, this doesn't include port number.
In case of no namespace being used, on line 1024 loc.host is being used and everything is fine.
I have taken a copy of the file and changed line 1050 to use host and everything works fine.
Found github issue with that, it is fixed in 1.4.x:
https://github.com/Automattic/socket.io-client/issues/812
No need to mess with ports, it pretty much should work just by
var admin_socket = io('/admin');
var user_socket = io('/user');
I don't think there is any way to get the auto port discovery to work without modifying the actual Socket.io code or waiting for a fix. The simplest thing you could do is just insert the current location.port including a colon before your namespace.
var admin_socket = io(':' + location.port + '/admin');
var user_socket = io(':' + location.port + '/user');
Or create a new function that will create a socket for you.
function sio(nsp) {
return io(':' + location.port + nsp);
}

Categories

Resources