Managing multiple websocket subscriptions with a single connection object within a Javascript function

Note: The client-side WAMP implementation is done using Autobahn.js, and promises are handled with when.js.

The goal is to establish a re-usable code structure where only one websocket 'session' or connection exists. Whenever a developer wants to subscribe to a topic using Autobahn, they should be able to do it using the existing connection object if it is already present; otherwise, a new one needs to be created.

The current issue arises when the connection already exists, requiring the use of setTimeout() to ensure that it is indeed connected before duplicating the subscription code. This workaround approach is not ideal.

The following is the current code snippet:

(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);

                    // Perform actions with the received data ...
                });

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

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

An obstacle occurs when adding another subscribeTo() immediately after the previous one. In this case, the connection is no longer null, but also not yet fully connected. Therefore, a setTimeout() delay becomes necessary as shown below:

// Other subscribeTo calls 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 call works, while the second requires a setTimeout() for the connection readiness

// Check if connection is not null...
} else {
    setTimeout(function() {
        connection.subscribe(topic... etc...) // Is there a better way?
    }, 1000);
}

Eliminating the setTimeout() results in an error stating "Autbahn is not connected".

Is there a more efficient way to maintain a single, reusable connection without resorting to code duplication, or should I accept creating a new connection for each subscription due to the promise handling? Maybe leveraging promises could provide a solution here, although my familiarity with them is limited.

Answer №1

This is unnecessarily complicated and incorrect. It is best to subscribe 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 handle automatic reconnections for you (and perform WAMP-CRA authentication if needed). init() is automatically invoked upon a reconnection. It is advised not to use the raw Session object unless you are familiar with it.

Additionally: topics must be URIs starting with either the http or https scheme. The use of serialized objects (JSON) is not permitted.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issues with displaying all series values on hover in Highcharts tooltips are being experienced

https://i.sstatic.net/7NVBM.gif The desired outcome is for the tooltip to show all 7 bar values for a specific yAxis entry. However, it currently only displays the values dynamically for 3 to 7 of the bar values based on the cursor position in the yAxis ...

What is the process of including data in Vue using refs?

My goal is to click a button and have the page scroll up or down. However, I need references for each span I add in order to include an index. The issue arises when trying to incorporate this index into the method. How can I add data to these references? ...

I'm puzzled as to why my login isn't functioning unless I had previously signed up

I'm encountering an issue with logging in an existing user and displaying their name on the navbar. The error occurs when trying to access the username property of a null value. Interestingly, this error only occurs after signing up a new user and imm ...

Classify JavaScript Array Elements based on their Value

Organize array items in JavaScript based on their values If you have a JSON object similar to the following: [ { prNumber: 20000401, text: 'foo' }, { prNumber: 20000402, text: 'bar' }, { prNumber: 2000040 ...

How can one effectively separate logic in AngularJS for optimal performance?

I've been diving into AngularJS and it's been quite fascinating, although I do run into some architectural challenges at times. Let me illustrate with an example. Imagine we have an application that enables users to create bills. Each bill consi ...

Despite population, MongooseJS still renders blank array

Currently in the process of developing an application using Node.js with MongooseJS as the middleware for handling database operations. Encountering an issue with nested schemas, specifically with one of them being populated incorrectly. Despite tracking ...

What is the process for retrieving wallet transactions using Alchemy websockets?

I am trying to retrieve all new transactions from a specific wallet using the code provided. However, I am encountering an issue when using the function tx["transaction"]["from"] to filter transactions based on the specified wallet. I am utilizing Alchemy ...

Are there any JavaScript tools for adding notes to text?

I’ve searched online but haven’t had any luck. Is there a tool available that allows for annotating text selections, even those that overlap? The scenario is that multiple users will be given the same text and need to annotate different selections in ...

"Incorporating a hyperlink into a newly added table row with the help

When utilizing jQuery, I am able to dynamically add rows to a table with each row containing an anchor tag. However, when attempting to populate the anchor tags with links using jQuery, the links do not appear as expected. Strangely enough, the other data ...

Numerous inline notations in html code

I need help figuring out how to prevent a hyperlink from opening a new tab by commenting out the HTML code. <a href="<!--http://www.google.com=-->" target="_blank" onclick="javascript:alert('Navigation Prevented')">CLICK HERE FOR GOO ...

Enabling and disabling multiple input fields based on the status of a checkbox in order to manage dynamic inputs

I need help with a situation involving dynamic input fields and checkboxes. My goal is to disable the input field if the checkbox with the corresponding ID is checked. Here is the PHP code snippet: <table class="table table-striped"> <thead& ...

Click on the link within the Checkbox label on MUI

I am working on creating a checkbox for the "Terms of Use," using FormControlLabel to nest a Checkbox. However, I also need to include a link that opens a Dialog component displaying the terms. The challenge is that clicking on the link checks the checkbox ...

Having trouble with react-bootstrap Navbar not displaying correctly in React JS?

I am currently working with ReactJS and Bootstrap 4. I am using the react-bootstrap module to render the Navbar, but I am encountering issues with the rendering. I suspect that there may be a conflict between Bootstrap 4 syntax and another Bootstrap 3 synt ...

Scroll the second div to align with the first div

I am in need of a scrolling set of divs that functions like a slide show. I have been searching for a solution but haven't found one yet. Is there a way to make the commented-out div scrollable by clicking somewhere on the page or an arrow image? I wa ...

Troubleshooting: Google Tag Manager showing a blank page

After attempting to integrate Google Tag Manager into my website, I encountered a strange issue where upon refreshing the page, it would go completely blank with no specific error displayed. I followed the only upvoted solution from a thread on Stack Over ...

It is not possible to assign a unique name to the custom attr() method

The code provided by someone else is working perfectly fine. However, when I try to rename the attr method, for example to attrx, I encounter an error. The error message I receive after renaming the method is: TypeError: arg.attrx is not a function Below ...

What is the best way to extract the primary base64 value from reader.result?

After successfully retrieving the base64 value of my file, I noticed that along with the value, I am also getting the type of file and the type of string. However, I only require the actual value in order to send it to the backend. Code for converting fil ...

A system-wide meltdown occurs when attempting to utilize the 'map' property of an undefined element, resulting in a TypeError

Essentially, my goal is to retrieve the techs state from the store code ({ getTechs, tech: {techs, loading}}) => { useEffect(() => { // getTechs(); //eslint-disable-next-line }, []); and utilize it in this section code continuation {!loa ...

Jquery(Ajax) call encountered a problem when attempting to send the object

Struggling to send data to a MongoLab DB using JS and JQueryAjax call. The issue lies in being able to see the OID in the DB but no data is actually populated. Upon checking the code and network settings, it's evident that the payload always remains e ...

I'm looking to create a JavaScript function that will extract each element from a div and then apply a corresponding CSS block to activate it

My goal was to create this function using Flask, but it seems that only JavaScript is capable of achieving it. This is my first attempt at coding it. Here's the code snippet: const navSlide2 = () => { const burger = document.querySelector(&apos ...