Handling multiple websocket subscriptions, but only one connection object, in a single Javascript function

StackOverflow https://stackoverflow.com/questions/19634882

Pregunta

Note: I'm using Autobahn.js for the client-side WAMP implementation, and when.js for promises.

I'm trying to create re-usable code so that only one websocket 'session', or connection exists, and whenever a dev wants to subscribe to a topic using autobahn, they can just use the current connection object to do so if it already exists; else a new one is created.

My issue is that, if the connection already exists, I have to use a setTimeout() to wait for a second to make sure it's actually connected, and then duplicate all the subscription code - I don't like this at all.

Here's my current code:

(function() {
    var connection = null;

    subscribeTo('subject', __userId, __token, function(onconnect) {
        console.log('Yay, connected');
    });

    function subscribeTo(subject, userId, token, onConnect, onDisconnect) { 
        if (connection === null)
        {   
            connection = new ab.Session('ws://localhost:8080', function(onopen) {

                connection.subscribe(JSON.stringify({subject: subject, userId: userId, token: token}), function(subscription, data) {
                    data = $.parseJSON(data);

                    // Do something with the data ...
                });

                if (typeof onConnect === 'function') { 
                    onConnect(); 
                }

            }, function(onclose) {
                if (typeof onDisconnect === 'function') { 
                    onDisconnect(); 
                }
            }, { 'skipSubprotocolCheck': true });
        }
    }
})();

Great. Now the issue is, what if I have another subscribeTo() straight after the previous one? Connection won't be null any more, but it also won't be connected. So the following is what I have to do:

// subscribeTo() multiple times at the top ...

subscribeTo('subject', __userId, __token, function(onconnect) {
    console.log('Yay, connected');
});

subscribeTo('anothersubject', __userId, __token, function(onconnect) {
    console.log('Yay, connected');
});

// The first one works, the second one requires a setTimeout() for the connection

// if connection is NOT null...
} else {
    setTimeout(function() {
        connection.subscribe(topic... etc...) // Really!?
    }, 1000);
}

Remove the setTimeout() and you'll get an error saying that "Autbahn is not connected".

Is there a better way to have a single, re-usable connection, without code-duplication, or am I doomed to create a new connection for each subscription because of the promises (perhaps I can use promises to my advantage here, although I haven't used them before this)?

¿Fue útil?

Solución

This is all way too complex, unneeded and wrong. You want to do your subscribes in response to a session being created:

var session = null;

function start() {
   // turn on WAMP debug output
   //ab.debug(true, false, false);

   // use jQuery deferreds instead of bundle whenjs
   //ab.Deferred = $.Deferred;

   // Connect to WAMP server ..
   //
   ab.launch(
      // WAMP app configuration
      {
         // WAMP URL
         wsuri: "ws://localhost:9000/ws",
         // authentication info
         appkey: null, // authenticate as anonymous
         appsecret: null,
         appextra: null,
         // additional session configuration
         sessionConfig: {maxRetries: 10, sessionIdent: "My App"}
      },
      // session open handler
      function (newSession) {
         session = newSession;
         main();
      },
      // session close handler
      function (code, reason, detail) {
         session = null;
      }
   );
}

function main() {
   session.subscribe("http://myapp.com/mytopic1", function(topic, event) {});
   session.subscribe("http://myapp.com/mytopic2", function(topic, event) {});
   session.subscribe("http://myapp.com/mytopic3", function(topic, event) {});
}

start();

The ab.launch helper will manage automatic reconnects for you (and also do WAMP-CRA authentication if required). init() is then automatically called again when a reconnect happens. Using raw Session object is not recommended (unless you know what you are doing).

Also: topics must be URIs from the http or https scheme. Using serialized objects (JSON) is not allowed.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top