Issue with handling multiple messages in WebSocket responses as Promises

In my web project using angularjs, I have the task of downloading data every second via a WebSocket. However, I encounter issues with handling multiple requests of different types. Although I utilize Promises to structure the requests, sometimes the responses end up in the wrong function. To provide an example:

I've created a service responsible for making the requests and receiving Promise-based results.

socketService.$inject = [];
function socketService(){
    let service = this;

    let server = new WebSocket('ws://localhost:8090');
    let isOpen = false;

    server.onopen = function(){
        isOpen = true;
    };

    server.onerror = function(){
      //TODO handle error
    };

    service.sendRequest = function(action, data){
        return new Promise(function (resolve, reject) {

            if (isOpen) {
                server.send(encodeRequest(action, data));
                server.onmessage = function (message) {
                    resolve(JSON.parse(message.data));
                }
            }

            server.onopen = function () {
                server.send(encodeRequest(action, data));
                server.onmessage = function(message) {
                    resolve(JSON.parse(message.data));
                    isOpen = true;
                }
            };

            server.onerror = function (error) {
                reject(error);
            }
        })
    };

}

This is how I use it:

socketService.sendRequest('get_events', {})
  .then(function (response) {
      //DO SOMETHING WITH THE RESPONSE
      return socketService.sendRequest('get_history', {
          fromDate: value,
          toDate  : value,
          tag     : value,
          event   : value
      })
  })
  .then(function (response) {
      //DO SOMETHING WITH THE RESPONSE
  });

The issue arises when I make concurrent requests. If I trigger multiple requests within seconds and then introduce a new request at the same time, the responses become mixed up. It seems that if I send a request and before its response, another request is made, the first response goes to the second request.

I am puzzled by this behavior as I'm returning a new Promise each time, which should associate the response with the correct Promise instead of mixing them up.

While I've learned that a resolved Promise cannot be reused (it will return the last result), I continuously create new ones. Can someone shed light on what might be happening and suggest potential solutions?

Answer №1

To ensure each response is matched to the correct request, it's important to assign a unique ID to each message. Before delving into coding this, consider exploring json rpc 2.0, a standard with various javascript implementations that can simplify this process for you. A reliable option I've had success with is https://github.com/jershell/simple-jsonrpc-js

You mentioned your concerns about Promise code not functioning as expected. The thing is, Promises might not always work as anticipated. Your Promise code modifies the server's callback methods (onOpen, onMessage, etc.) to trigger the promise's "resolve" function. However, since there's only one server despite having multiple promises, each new Promise just assigns the server's callback methods to a fresh resolve function.

But... instead of going through all that trouble, consider leveraging solutions that have already been developed, like JSON RPC 2.0.

Duncan

Answer №2

I encountered the same challenges with WebSocket messages behaving like events. To address this issue, I developed a library that enables writing Promise-based functions for sending and receiving messages.

Check out my library here!

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

Tips for keeping Fancybox from deleting the selected thumbnail

New to using fancybox and running into some issues.. starting to regret adding it. I have a row of thumbnails, all good, but when I click one it opens the THUMBNAIL instead of the actual link and on top of that, it DELETES the thumbnail from the DOM. I tr ...

The error being thrown is related to Next.js 13 cache setting of 'no-store'

Check out this snippet of code async function fetchData() { const response = await fetch('http://127.0.0.1:1337/api/posts', { method: 'GET', headers: { 'Content-Type': 'application/json', Author ...

What is the process for reverting variables back to their original values using pure Javascript?

I am working on developing a hangman game using vanilla javascript and I need some assistance with resetting the game after a player loses. Specifically, I would like to: 1. Reset the "guessRemain" variable. 2. Clear out the "guess" id so that none of the ...

Utilizing Jquery's .load function will temporarily deactivate all other functions

Season's Greetings everyone! I have a unique personal messaging system on my website that utilizes jQuery for message display and manipulation. Let's delve into the specific file that controls this functionality: <!-- Fetching and displaying ...

Manipulating Angular forms: toggling a $dirty attribute within a personalized directive

We have developed a unique directive called check-button, which generates a styled checkbox with specific functionality. For this directive to work properly, I need to include ng-form so that I can utilize the formCtrl within the directive. While I have b ...

The npm script for running Protractor is encountering an error

Currently, I am facing an issue while trying to execute the conf.js file using an npm script. The conf.js file is generated within the JSFilesRepo/config folder after running the tsc command as I am utilizing TypeScript in conjunction with protractor-jasmi ...

Developing a collection of reusable components in a Javascript bundle for enhanced efficiency

I currently have a backend rendered page (using Django) that I want to enhance by incorporating components from PrimeVue and a markdown editor wrapped as a Vue component. Previously, we utilized some simple animations with jQuery which we included directly ...

CompletePage script, individual automatic scrolling

Having trouble with my fullPage.js implementation. I have a total of 5 sections and I'm trying to set different scrolling behaviors for each section. Specifically, I want Sections 1 through 3 to auto-scroll and Section 4.1 to 4.2 to use normal scroll. ...

Dealing with a Node and Express server can be tricky, especially when trying to proxy a POST request along with parameters. You might encounter the error

I am trying to forward all requests made to /api/ from my local node server to a remote server, while also adding some authentication parameters to them. Everything works smoothly for GET requests with query parameters and POST requests without specifying ...

Encountering a malfunction while executing an npm command specified in the package.json file

Currently, I am following a tutorial on Node, React, and Express on Udemy. In the tutorial, when I execute the command npm run data:import I encounter the following error: undefined npm ERR! code ELIFECYCLE npm ERR! errno 1 ...

What is the best way to show instructions immediately upon receipt of a response?

I'm currently working on developing a website similar to ChatGpt using the OpenAI API for GPT. However, there is a delay in generating responses with GPT taking a few seconds. As a result, my code only displays the instruction once the response from G ...

Utilizing JSON data as a variable for handling in a Handlebars view within a Node.js/Express application

I am currently seeking a solution to display a view that includes a variable with data fetched from an API. My technology stack involves express, handlebars, and request. Here is the code for the web server's router: const express = require('ex ...

Could someone provide a detailed explanation of exhaustMap in the context of Angular using rxjs?

import { HttpHandler, HttpInterceptor, HttpParams, HttpRequest, } from '@angular/common/http'; import { Injectable } from '@core/services/auth.service'; import { exhaustMap, take } from 'rxjs/operators'; import { Authe ...

Exploring ways to simulate promises online for integration into my personal Vue.js project

Is it possible to import and activate a mocker in the main.js file of a Vue.js project? Can it be done after: import Vue from 'vue' App from './App' ? How do I initiate it, by the way? Thank you in advance for sharing your thoughts. ...

Preserving data in input fields even after a page is refreshed

I've been struggling to keep the user-entered values in the additional input fields intact even after the web page is refreshed. If anyone has any suggestions or solutions, I would greatly appreciate your assistance. Currently, I have managed to retai ...

Check the feature that retrieves data from a `json` file

In my util file, I have a function that imports and checks whether a given sectionUUID has a video in the JSON file. import multipleVideos from '../data/videos.json' function hasSectionMultipleVideos (sectionUUID) { return multipleVideos.vide ...

JavaScript - Not a Number

I am currently facing an issue while attempting to calculate the Markup of a product. I keep receiving a 'NaN' error in my console, which I understand stands for Not a Number. However, I am struggling to identify and rectify the root cause of thi ...

Why has Jasmine decided not to wait for my promises to finish?

Utilizing the FileSystem API to generate a directory with 2 entries for a test, I am facing an issue where Jasmine does not wait for the promise to resolve before executing the test, resulting in failure. Despite using the async wrapper, the problem persis ...

Storing data from an API response into the localStorage using Vue.js upon clicking

My objective is to save specific data in the browser's localStorage upon clicking a link. However, the output I receive is either undefined or completely empty. <li v-for="(category, index) in categories" :key="index"> ...

How can we stop the anchor jump caused by a third-party script?

I'm currently utilizing a third-party script (details provided below) to divide a form into multiple ajax'd pages. However, when I attempt to move on to the next page, it immediately jumps to an anchor at the top of the form. This behavior is unn ...