I'm trying to access socket.io in an express-generator app, but getting a null object - node.js

I've built a web app with express generator. I'd like to be able to send updates to the browser from a number of different modules.
However, I'm not quite sure why the solution I've put together, below, doesn't work.
I know that the exports.initialize() function is being called, through logging to the console, but the error I'm getting, cannot read property 'emit' of null suggests that socket.io is not being initialized, because it's returning a null object.
I've created a module containing the below wrapper:
const sio = require('socket.io')
let io = null
exports.io = function () {
return io
}
exports.initialize = function(server) {
console.log("init")
return io = sio(server)
}
I've initialised the module in my app.js file, like so:
// Create the http server
const server = require('http').createServer(app);
// Create the Socket IO server on
// the top of http server
const io = require('./app_modules/sockets').initialize(server)
and then, in modules where I need to send information to the browser, I'm calling the sockets module like this:
const io = require('./sockets').io()
Can anyone help me understand why this isn't working, and what I can do to fix it?

In order to start a Socket.IO server, you need to invoke the Server constructor. The io constructor is only for the client side.
Your sockets module should look like this:
const sio = require('socket.io')
let io = null
exports.io = io
exports.initialize = function(server) {
io = new sio.Server(server);
return io
}
And in modules where you need to send information to the clients, you should use something like this:
const io = require('./sockets').io

Related

Error on creating socket server with socket.io on typescript

Im new at socket io and im trying to use typescript on the project so i got the error of the image on start the socket server, i already tried to change the import to import * as socketIo from 'socket.io' but nothing changes, i dont know if is some version issue or im doing something wrong.
the error:
code:
Type declaration for socket.io does not contain default export. You can check it in its index.d.ts. It contains the following:
export { Socket, ServerOptions, Namespace };
That's why to init socket.io server object you need to use the following instruction:
const app = express();
const httpServer = new http.Server(app);
const io = new socketio.Server(httpServer);

Node.js get same instance of module accross different classes

I've a main class (app.js) where I declared an instance of socket-io and I would like to know how is possible to get same instance of socket-io inside another classes.
app.js
var io = require('socket.io')();
//initialize socket and more related do web socket
routes.js
var io = ?? //How get same var io from app.js?
On Node.js, is possible to do that? I need to manipulate some informations from socket-io but I would like to avoid write a single file with all logic inside.
Let's say you have a file routes.js and this is a file inside which you want to access the instance of socket-io which you have created on app.js. Then you can pass this var io inside the routes.js file that will pass the same instance of socket-io like this,
Inside app.js
var io = require('socket.io')();
//pass the `io` inside the route file
require('routes')(io);
Inside routes.js
module.exports = function(io) {
//your route codes here that can access `io`
};

How to connect multiple sockets to sails in test

I have a messaging controller setup in sails.js and want to test it with multiple clients to see if the pub/sub code works. I set up a test file
var socketIOClient = require('socket.io-client');
var sailsIOClient = require('sails.io.js');
var socket1 = socketIOClient;
var client1 = sailsIOClient(socket1);
var socket2 = socketIOClient;
var client2 = sailsIOClient(socket2);
var socket3 = socketIOClient('http://localhost:1337', {'force new connection': true});
var client3 = sailsIOClient(socket2);
...
client1.socket.get... works and says it is subscribed.
client1.socket.post... works and posts a message to the DB.
So I want to test that a client can receive the notification when a new message is posted. However, when I post from either client1 or client2, it posts from both. Essentially, they are linked to the same socket object or something like that, but I don't know where. So I want to connect multiple sockets, and I've tried variations like socket3 and client3, but get the following problem:
client3.socket.get... and client3.socket.post... and other variations (forceNew, multiplexing, etc.) each hang up and don't resolve.
Example of hang up:
sails.log('posting...');
client3.socket.post('/v1.0/messaging', data, function(body, JWR){
sails.log('posted');
done();
});
Only posting... is logged in this way, but posted is logged if using client1 or client2.
My question:
How can I connect multiple clients to my sails api to test if my pub/sub controller works?
I can't test it right now, but you could try this
var socketIOClient = require('socket.io-client');
var sailsIOClient = require('sails.io.js');
// Instantiate the socket client (`io`)
var io = sailsIOClient(socketIOClient);
// prevents socket to connect with it's default origin
io.sails.autoConnect = false
// Ask the client to create two socket connections
var socket1 = io.sails.connect('http://localhost:1337');
var socket2 = io.sails.connect('http://localhost:1337');
// Test it
socket1.get(url, data, cb)
socket1.post(url, data, cb)
socket2.get(url, data, cb)
socket2.post(url, data, cb)
// If you want to configure and use the "eager" instance
io.sails.url = 'http://localhost:1337';
io.socket.get(url, data, cb)
This way, you would create several SailsSocket instance instead of using the "eager" instance.
When you use sails.io.js in a browser, io.socket contains the socket instance (called "eager instance" in the comments) which will automatically try to connect using the host that the js file was served from. io.sails.connect() allows you to create other instances.
The correct syntax for actual version of socket.io should be
//first socket
var socket1 = socketIOClient('http://localhost:1337', {'forceNew: true});
//second socket
var socket2 = socketIOClient('http://localhost:1337', {'forceNew: true});
See socket.io docs http://socket.io/blog/socket-io-1-2-0/#

Cannot access io object in session.socket.io

I am using session.socket.io for my app
o = require('socket.io').listen(tmpServer),
appCookieParser = express.cookieParser(settings.cookie.secret),
appRedisStore = new RedisStore(),
sessionIO = new SessionSockets(io, appRedisStore, appCookieParser
App.app.use(appCookieParser)
App.app.use(express.session({
store: appRedisStore
}))
Note that App is a global variable which holds some of my app data and some helper functions, as I followed the LearnAllTheNodes application structure.
Then I define the callback on connection
sessionIO.on('connection', socketHandler)
where socketHandler is a function returned by a require call.
module.exports = function(err, socket, session) {
console.log(io.sockets.clients('a'))
socket.join('a')
console.log(io.sockets.clients('a'))
}
According to the documentation I should have access to my io object, but I am always getting the error that io is not defined.
Note that if I am emitting some events or listening for some events in the sockatHandler I am getting/sending them properly. Just I have no access to io.
UPDATE
It turns out it works perfectly if I am implementing the callback function as an anonymous function. The documentation is confusing, it should be: you can use io if you have a reference to it.
You seem to have forgotten to define io which here should be the listener.
According to the code you display, you should probably have something like
var app = express();
var server = http.createServer(app);
var io = socketio.listen(server);
Here's an example of a complete application using express, socket.io and session.socket.io.
To make my app less crowded I've updated the socketHandler so it takes all my socket related objects
socketHandler(sessionIO, io)
and I am handling the socket operations in another module via these objects.

Node.js - sharing sockets among modules with require

I'm using socket.io. In app.js I set up it and whenever a connection is established, I add the new socket to sockets array. I want to share sockets among modules such as routes by require(). However, app.js also requires the routes, so it forms a require loop. Here's the code.
// app.js
var route = require('routes/route')
, sockets = [];
exports.sockets = sockets;
// route.js
var sockets = require('../app').sockets; // undefined
How can I resolve the loop? Or are there other approaches?
You could do all your socket.IO work inside the route file
var route = require('routes/route').init(io)
with in routes.js
var io;
exports.init = function(io) {
io = io
}

Resources