0

I need to emit data only to the user that request it. So far I get:

app.js file (server):

var express = require('express');
var app = express();

app.set('view engine', 'ejs');

app.use(function(req, res, next){
    req.io = io;
    next();
});

var mainPath = require('./routes/mainPath.js');
app.use('/', mainpath);

port = 8000;
var io = require('socket.io').listen(app.listen(port));

io.on('connection', function(socket){
console.log('connected');
});

mainpath.js file:

var express = require('express');
var app = express();
var router = express.Router();
var request = require('request');

    router.post('/path', function(req, res){
request('http://google.com', function (err, resp, content_body){
    req.io.emit('socketio emit', {socketioEmit : body});
});
    });

// [!]

module.exports = router;

[!] problem appear when... request used here for example (or any fast executing data), grab data faster then socket.io connection is established, and the user don't receive data.

io.js file (client):

var socket = io();
socket.on('connect', function(){
console.log('connected');
});

socket.on('socketio emit', function(emit){
console.log(emit.socketioEmit);
});

mainpath.ejs file:

<html>
<head></head>
<body>
<div class="form_seo_wrapper">
    <form action="/path" method="post">
        <input type="text" name="input_name" />
        <input type="submit" value="go" />
    </form>
</div>
</body>
</html>

path.ejs file:

<html>
<head></head>
<script src="socket.io.min_v1.7.2.js"></script>
<body>
<h1>Output:</h1>
</body>
<script src="io.js"></script>
</html>

Any ideas? BTW is there any possibility to not break socket connection when user enter from '/' to '/path' ?

webmasternewbie
  • 167
  • 1
  • 2
  • 16

1 Answers1

2

In your app.js you can use

global.io = require('socket.io').listen(app.listen(port));

instead of

var io = require('socket.io').listen(app.listen(port));

and in mainpath.js file simply use this to emit:

io.emit('socketio emit', {socketioEmit : data});

You have to save the socket Id when that client attempts to connect with his userId in some storage in socket.on('connection') callback

you can fetch that socketId when you want to emit data and emit data like this

io.sockets.to(socketIdOfUser)

One thing quick you can do is create room against each user id and emit data only to that room. This way you dont have to manage sockets in your storage

ON NOT BREAKING Socket CONNECTION ON ROUTE CHANGE Please Update your question with the template engine or FrontEnd Framework you are using and the structure of app

Asif Saeed
  • 1,985
  • 14
  • 24
  • Thank you for your input! I have updated my question so you can adjust your answer better. I think the problem is with **socket** data - _io.on('connection', function(socket)_ - I can acces io in routes but I can't access io.socket... – webmasternewbie Jan 30 '17 at 16:00
  • Thanks again for your valuable input! I did use rooms - socket.join(room); with ID of an socket. However when I evaluate data after _req.io.emit('socketio emit', {socketioEmit : data});_ in **mainpath.js file** sometimes socket connection with server appear AFTER data emit, so user simply don't see the data. Any idea how to resolve this? For not breaking connection on route change - is cookie (with ID) a good solution, or is there simpler method? – webmasternewbie Jan 31 '17 at 21:32
  • i cant see from where the data variable is coming from in mainpath.js. I think all of your issue are related to ejs end socket-io connections. I would suggest to connect socket io in main main index.js file so socket-io is connected at the top level and accessible everywhere and it wont disconnect and reconnect at each route change aswell – Asif Saeed Feb 01 '17 at 04:47
  • https://code.tutsplus.com/tutorials/real-time-chat-with-nodejs-socketio-and-expressjs--net-31708 See this example for reference socket-io is connected under the head tag – Asif Saeed Feb 01 '17 at 04:49
  • "i cant see from where the data variable is coming from in mainpath.js." - right... sorry for that, **updated!** you can glance it. I even try to put _io.on('connection'_ directly in router.post - to no avail cause of connection break from "/" to "/path". Data (in this example - request body) must be emitted **after** connection with the client is establish - so he (client) can grab it. So APP.JS file with _socket.io connection_ -> MAINPATH.JS with _router.post_ and _require_ in -> PATH.EJS with _socket.io connect_. How to emit async request when PATH.EJS is ready? – webmasternewbie Feb 01 '17 at 15:45
  • i dont think i am getting you – Asif Saeed Feb 01 '17 at 16:29
  • I'm simply talking about data flow. I did partially resolve this problem by moving io.on('connection', function(socket){... to router.post. By async request I mean every similar function in node run of it's own. So if one finish before established connection it's output won't be be visible, if the other finish after, it output will be visible for user. So we need to make sure that user is connected by socket.io and then output data from all those functions/requests. I guess I need to refactor some code to properly use of socket.io connection callback. Or is there any other way? – webmasternewbie Feb 04 '17 at 13:27
  • i will recommend you follow this structure. https://github.com/OmarElGabry/chat.io – Asif Saeed Feb 04 '17 at 17:21