简体   繁体   中英

NodeJS, SocketIO and Express logic context build

I read a lot about Express / SocketIO and that's crazy how rarely you get some other example than a "Hello" transmitted directly from the app.js. The problem is it doesn't work like that in the real world ... I'm actually desperate on a logic problem which seems far away from what the web give me, that's why I wanted to point this out, I'm sure asking will be the solution ! :)

I'm refactoring my app (because there were many mistakes like using the global scope to put libs, etc.) ; Let's say I've got a huge system based on SocketIO and NodeJS. There's a loader in the app.js which starts the socket system.

When someone join the app it require() another module : it initializes many socket.on() which are loaded dynamically and go to some /*_socket.js files in a folder. Each function in those modules represent a socket listener, then it's way easier to call it from the front-end, might look like this :

  // Will call `user_socket.js` and method `try_to_signin(some params)`

  Queries.emit_socket('user.try_to_signin', {some params});

The system itself works really well. But there's a catch : the module that will load all those files which understand what the front-end has sent also transmit libraries linked with req/res (sessions, cookies, others...) and must do it, because the called methods are the core of the app and very often need those libraries.

In the previous example we obviously need to check if the user isn't already logged-in.

  // The *_socket.js file looks like this :

  var $h = require(__ROOT__ + '/api/helpers');

  module.exports = function($s, $w) {

    var user_process = require(__ROOT__ + '/api/processes/user_process')($s, $w);

      return {

        my_method_called: function(reference, params, callback) {

          // Stuff using $s, $w, etc.

        }

  }

  // And it's called this way :

  // $s = services (a big object)
  // $w = workers (a big object depending on $s)
  // They are linked with the req/res from the page when they are instantiated

  controller_instance = require('../sockets/'+ controller_name +'_socket')($s, $w);

  // After some processes ...

  socket_io.on(socket_listener, function (datas, callback) {

       // Will call the correct function, etc.

       $w.queries.handle_socket($w, controller_name, method_name, datas);

  });

The good news : basically, it works.

The bad news : every time I refresh the page, the listeners double themselves because they are in a loop called on page load.

Below, this should have been one line :

在此输入图像描述

So I should put all the socket.on('connection'...) stuff outside the page loading, which means when the server starts ... Yes, but I also need the req/res datas to be able to load the libraries, which I get only when the page is loaded !

It's a programing logic problem, I know I did something wrong but I don't know where to go now, I got this big system which "basically" works but there's like a paradox on the way I did it and I can't figure out how to resolve this ... It's been a couple of hours I'm stuck.

How can I refacto to let the possibility to get the current libraries depending on req/res within a socket.on() call ? Is there a trick ? Should I think about changing completely the way I did it ?

Also, is there another way to do what I want to do ?

Thank you everyone !

NOTE : If I didn't explain well or if you want more code, just tell me :)

EDIT - SOLUTION : As seen above we can use sockets.once(); instead of sockets.on(), or there's also the sockets.removeAllListeners() solution which is less clean.

Try As Below.

io.sockets.once('connection', function(socket) {
  io.sockets.emit('new-data', {
    channel: 'stdout',
    value: data
 }); 
});

Use once instead of on.

This problem is similar as given in the following link.

https://stackoverflow.com/questions/25601064/multiple-socket-io-connections-on-page-refresh/25601075#25601075

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM