Socket.io middlewhere functions - javascript

I am trying to seperate logic in my socket.io server but i am experiance some issues.
say for instance i have the following:
io.on('connection', function (socket) {
var fileModule = require('./costum_modules/FileModule.js')(io);
app.use(fileModule);
});
Now inside the fileModule i have the following code:
var fileModule = function (socket) {
socket.on('userData', function(msg){
var i = 0;
});
}
module.exports = new fileModule();
Sadly the socket i undefined.
My question is can i do it like this or is it not possible to pass a singleton to another file and make it read from the same object?

You can use other files to break up your logic, but there are a couple issues with your code.
First, I think Hacketo is correct that you don't want to do new fileModule(), just:
module.exports = fileModule;
Second, when call require, you are passing the global socketIO object (io). You should pass it the socket you get in the connection handler. E.g.
require('./costum_modules/FileModule.js')(socket);
I think that will work to move some of your socket.io message handling code into a module. Now your socket will respond to userData messages from a client. However, unless you have some custom application, I don't think app.use is going to do what you expect. You can't hook web socket handlers into an Express/Restify/Connect/Whatever middleware chain. But you could write a middleware that sends a message to your socket server.
If you are just trying to share the session between your app and socket server, try this SO answer.

Related

socket.io - socket is not defined on client only

I'm running two instances of socket.io on my local machine (two namespaces). The present issue is that when trying to connect from the client side (to any namespace), I get the following error:
Uncaught ReferenceError: socket is not defined
I tested this without custom namespaces and the same issue arose. The server side is just fine as I can emit events.
The Client code looks like this:
Client
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js"></script>
<script>
var socketOptions = {};
socketOptions.transports = ['polling'];
var client = new PlayClient();
var playSocket = io.connect('http://localhost:8044/clients', socketOptions);
playSocket.on('connect', function(socket) {
console.clear();
console.info("CLIENT: Connected.");
socket.on("client:change scene", function(newSceneId) {
console.log(newSceneId);
client.changeScene(newSceneId);
});
});
</script>
It looks like I just overwrote the socket. So, basic troubleshooting led me to this answer leading me to confirm that. However, passing (data) or something else instead still leaves socket undefined but with the console declaring: TypeError: undefined.
If I change .on('connect') to .on('connection'), the socket is no longer overwritten but fails to connect or receive any emitted events because the socket.io client does not understand the 'connection' event.
Any help with this is much appreciated, as I seem to be caught in a circular rut.
you seem to be confusing server side and client side events; they are pretty different. each client object can only be connected to a single server, while the server can receive many connections
maybe try something like:
var playSocket = io.connect('http://localhost:8044/clients', socketOptions);
playSocket.on('connect', function() {
console.clear();
console.info("CLIENT: Connected.");
}
playSocket.on("client:change scene", function(newSceneId) {
console.log(newSceneId);
client.changeScene(newSceneId);
});

Socket.io and Express not sending data

I'm trying to use socket.io to connect to this websocket api:
https://www.cryptocompare.com/api/#-api-web-socket-
(wss://streamer.cryptocompare.com)
I guess im not really understanding socket.io very much.
I created a blank html document:
<!doctype html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.slim.js"></script>
</head>
<body>
<div id="data-show">
</div>
<button id="connect-sock">Connect</button>
<button id="disconnect-sock">DISConnect</button>
</body>
<script src="index.js"></script>
</html>
index.js:
var socket = io('wss://streamer.cryptocompare.com')
console.log('connected')
var btn = document.getElementById('connect-sock')
var btn2 = document.getElementById('disconnect-sock')
var show = document.getElementById('data-show')
//I also tried adding an event listener to a button so when i clicked it, it would do this:
socket.emit('SubAdd', { subs: ['0~Poloniex~BTC~USD'] } )
//Same result of nothing.
socket.on('SubAdd', function(data){
console.log(data)
})
server.js:
var express = require('express')
var socket = require('socket.io')
var app = express()
var server = app.listen(4000, function(){
console.log("well met")
})
app.use(express.static('public'))
var io = socket(server)
io.on('connection', function(socket){
console.log('well met from socket connection', socket.id)
})
server.js is in a file named 'socket-test'. index.html and index.js are in 'socket-test/public/'
so for some reason, in server.js, socket.id will not log to console. its as if this function is being skipped over. but when i change the address in index.js to http://localhost:4000, i get socket.id in console... not sure whats going on there.
Edit: I rarely get socket id when using the wss://streamer.cryptocompare.com/ , sometimes I do, most of the time i dont. It usually works when I switch to localhost, run the server, stop the server, then switch back to the streamer, but if i reload, i dont get socket.id anymore.
I thought that all I was asking it to do here was emit subs to wss://streamer.cryptocompare then console.log(data) that it returns after emitting the subs.
am I missing something here?
Sorry in advance if its blatantly obvious that I'm missing something. I've only known about socket.io for maybe 3 days now, and only today have I watched a basic tutorial on youtube.
You don't need the Express code because in this case the server you want to talk to is on the cryptocompare server -- not a local server. This is captured in your code when you initialize the io object in the HTML file.
Of course, you could still use Node to talk to the cryptocompare websockets API if you're more comfortable with Node. But then you wouldn't need the in-browser JavaScript. Either way, what you need is to create some kind of client in any runtime that speaks websockets and can talk to the cryptocompare websockets API.
With regard to the code being skipped over -- you're right! It is. socket.io is an event driven WebSockets framework. This means that clients register their interest in certain kinds of events/messages, and when those are triggered special functions known as callbacks are called.
If it helps, you can think of those events like channels in a chat room -- if you're not in the right room, you won't see the messages for that room. So you'll need to know what messages you should be listening for, register your interest in those, and register callback functions for each one.
Thankfully cryptocompare has provided client code examples that should help you get an idea for the kinds of messages you should be listening for.
See here

any way to send a function with socket.io?

guys.
I want to send a function to browser with socket.io, but failed to do it.
On server side, I response a function with emit, but I get a undefined on browser.
Is there any way to get a function from server with socketio?
there is my code.
// server.js
var static = require('node-static');
var http = require('http');
var file = new(static.Server)();
var app = http.createServer(function(req, res) {
file.serve(req, res);
}).listen(8000);
io = require('socket.io').listen(app);
io.sockets.on('connection', function(socket) {
socket.on('schedule', function() {
console.log('SCHEDULE TASK');
socket.emit('schedule', function() { console.log('hello world'); });
});
});
// client.js
var socket = io.connect('http://localhost:8000');
socket.on('schedule', function(fn) {
fn();
});
socket.emit('schedule');
You cannot send an actual function. You could send a string of Javascript and then you could turn that into a function in the client.
But, I'd suggest you really ought to rethink what you're trying to do here. Generally, the client already has the code it needs (from the script tags that it downloaded) and you send the client data which it then passes to the code it already has or data that it uses to make decisions about which code that it already has to call.
If you show us the real world problem you're trying to solve, we can likely suggest a much better solution than sending a string of Javascript code to the client.
If you really wanted to send a function, you would have to turn it into a string first, send the string, then use the string to turn it back into a function in the client by using a Function object or eval() or creating your own dynamic script tag with inline source.
You can only send strings via socket.io, not functions. That being said, I suggest you to send function names instead.
//server.js
socket.emit('schedule', 'helloworld');
//client.js
function helloworld(){
console.log('hello world');
}
socket.on('schedule',function(name){
window[name](); //hello world
});

Socket.io with Cluster: iterating over all open connections

I'm running Socket.io multi-threaded with the native cluster functionality provided by Node.js v0.6.0 and later (with RedisStore).
For every new change in state, the server iterates over each connection and sends a message if appropriate. Note: this isn't "broadcasting" to all connections, it's comparing server data with data the client sent on connection to decide whether to send the server data to that particular client. Consider this code sample:
io.sockets.clients().forEach(function (socket) {
socket.get('subscription', function (err, message) {
if(message.someProperty === someServerData) {
socket.emit('position', someServerData);
}
});
This worked fine when there was only one process, but now, the client receives a message for each Node process (ie. if there are 8 Node process running, all clients receive the messages 8 times).
I understand why the issue arises, but I'm not sure of a fix. How can I assign a 1-to-1 relation from one process to only on client. Perhaps something using NODE_WORKER_ID of Cluster?
This previous SO question seems somewhat related, although I'm not sure it's helpful.
This seems like a pretty common request. Surely, I must be missing something?
So if I get this straight you need to emit custom events from the server. You can do that by creating your own custom EventEmitter and triggering events on that emitter, for example:
var io = require('socket.io').listen(80);
events = require('events'),
customEventEmitter = new events.EventEmitter();
io.sockets.on('connection', function (socket) {
// here you handle what happens on the 'positionUpdate' event
// which will be triggered by the server later on
eventEmitter.on('positionUpdate', function (data) {
// here you have a function that checks if a condition between
// the socket connected and your data set as a param is met
if (condition(data,socket)) {
// send a message to each connected socket
// if the condition is met
socket.emit('the new position is...');
}
});
});
// sometime in the future the server will emit one or more positionUpdate events
customEventEmitter.emit('positionUpdate', data);
Another solution would be to have those users join the 'AWE150', so only they will receive updates for 'AWE150', like so:
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
if (client_is_interested_in_AWE) { socket.join('AWE150'); }
io.sockets.in('AWE150').emit('new position here');
});
Resources:
http://spiritconsulting.com.ar/fedex/2010/11/events-with-jquery-nodejs-and-socket-io/

Socket IO | How to get the client transport type on the serverside?

I need to know what transport method a client is using for some conditional statements on the nodeJS serverside.
Does anyone know how I can get that information? Is it held within the client object?
As of Socket.IO 1.0:
Client:
socket.on('connect', function() {
console.log(socket.io.engine.transport.name);
}
Server:
io.sockets.on('connection', function(socket) {
console.log(socket.conn.transport.name);
}
In socket.io 0.7.6
io.sockets.on('connection', function(client) {
console.log(io.transports[client.id].name);
});
April 2012, this works: socket.transport
I'm sure you can find it if you dig in the internals of a client object, although without knowing why you need this I have to recommend against this kind of check for 2 reasons:
Firstly, since it isn't in the API the developers have absolutely no responsibility to keep things backward compatible, so any given version might implement/store that information differently, which will only ripple into your own development and cause problems.
Secondly, and more importantly, I suggest you rethink your design, the communication with the server thru socket.io is built to be transparent to the method being used. There should be no difference on either side. That's the purpose of the library, designing an app that behaves otherwise is totally orthogonal to that idea.
for reference's sake and google stumbles:-
in case anyone is still using v0.9 (or possibly earlier)
you can access this info from client side like this:
var socket = io.connect();
console.log(socket.socket.transport.name); //log the name of the transport being used.
answer found on google groups https://groups.google.com/forum/#!topic/socket_io/yx_9wJiiAg0
I believe this will solve your problem. My trick here is to save the transport type on the HTTP Request object once the client connects. You can then pick it up in your callback later. First we tweak the Listener class:
var io = require('socket.io'),
io.Listener.prototype._onConnectionOld = io.Listener.prototype._onConnection;
io.Listener.prototype._onConnection = function(transport, req, res, up, head){
req.socketIOTransport = transport; // Take note of the transport type
this._onConnectionOld.call(this, transport, req, res, up, head);
};
And then below in the body of your app:
var socket = io.listen(app),
socket.on('connection', function(client){
console.log(client.request.socketIOTransport); // Lets check that transport
// ...
});
Hope this helps!
io.connect.managers['connect url/port'].engine.transport

Categories

Resources