Massive Memory Drain Due to XMLHttp POST Request

Is there a way to prevent XHR POST Memory leak in my web app? I have searched extensively for solutions but have not found any satisfactory answers. My issue is similar to the one described in this blog post that outlines the problem without offering any fixes.

My Dilemma: I am continuously sending large amounts of data (2Mb to 80Mb) to the server through POST requests, ranging from 10 to 300 requests. This problem does not occur with GET requests.

What can I do to resolve this? I have tried addressing circular references, scopes, closures, and more without success. Attempting to use the delete keyword during readystate changes, deleting previous XHR objects, reusing XHR objects, setting XHR references to null, and altering coding patterns all have not yielded positive results.

Below is a sample code illustrating the functionality I require:

 var base_string = "ABCDEFGHIJKLMNOPQUST01234567890!@#$%^&:ABCDEFGHIJKLMNOPQUST01234567890!@#$%^&ABCDEFGHIJKLMNOPQUST01234567890!@#$%^&";
            base_string += base_string;  
            base_string += base_string; 
            base_string += base_string; 
            base_string += base_string;  
            base_string += base_string;  
            base_string += base_string;  
            base_string += base_string;  
            base_string += base_string; 
            base_string += base_string;  
            base_string += base_string;  
            base_string += base_string; 
            base_string += base_string;  
            base_string += base_string;  
            base_string += base_string;  
            base_string += base_string;  
            base_string += base_string;  
            base_string += base_string;  
            this.sampleData = base_string;
            var dataToSend = this.sampleData.substring(0, 2000000);

           this.xhr = [];
           this.xhr[0] = new XMLHttpRequest();
           function sendRequest (){
               var Self = this;
               Self.xhr[0].onload = function (test) {
                   sendRequest ();
               };

               Self.xhr[0].open("POST", "http://localhost/upload.php" + "?n=" + Math.random(), true);
               Self.xhr[0].send(dataToSend);
           }
           sendRequest ();

How can I achieve this functionality without encountering memory leaks?

Answer №1

Consistently monitoring the size and volume of requests can be challenging when using XHR. It may be more suitable to explore alternatives such as WebRTC, Long Polling, or Web Sockets for better scalability. Trying to find a workaround within the limitations of XHR could lead to issues with scaling in the future.

Answer №2

Improve your code by removing the unnecessary use of Self and array, and also re-initializing xhr.

I have made a change to add a listener for the upload load event - a quick test shows that there doesn't appear to be any memory leaks (at least not at first glance).

// snippet
this.sampleData = base_string;
var dataToSend = this.sampleData.substring(0, 2000000);

function sendRequest() {
    var xhr = new XMLHttpRequest();
    xhr.upload.addEventListener('load', function(e) {
         sendRequest();
    });

    xhr.open("POST", "http://localhost/upload.php" + "?n=" + Math.random(), true);
    xhr.send(dataToSend);
}
sendRequest();

Answer №3

With each request sent, a new onload handler is added.

this.xhr[0].onload = function (test) {
    sendRequest ();
};

The previous handler remains in memory and isn't removed, causing a memory leak. The garbage collector can't free up the memory.

If you only need one event listener in your case, it's best to move the listener attachment outside the sendRequest function. By doing this, the memory leak issue should be resolved.

this.xhr = [];
this.xhr[0] = new XMLHttpRequest();
xhr[0].onload = function (test) {
    sendRequest ();
};
function sendRequest (){
    xhr[0].open("POST", "http://localhost/upload.php" + "?n=" +  Math.random(), true);
    xhr[0].send(dataToSend);
}
sendRequest (); 

UPDATE: Version 2

I've tested another version that shows even better results. My setup never exceeds 2.6G of memory usage. It's based on Jaromandas' work with the addition of removeEventHandler and delete.

function sendRequest (){
function run(e){
  xhr.upload.removeEventListener('load',run)
  sendRequest()
}
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('load', run);
xhr.open("POST", "http://localhost:2345/" + "?n=" +  Math.random(), true);
xhr.send(dataToSend);
delete xhr
}
sendRequest ();

Answer №4

Have you considered a more contemporary approach by using fetch...?

const endpoint = '/uploadData.php'
const options = {
    method: 'post',
    cache: 'no-cache',
    body: new ArrayBuffer(2000000)
}

function sendFetchRequest() {
    return fetch(endpoint, options)
        .then(response => response.blob())
        .then(sendFetchRequest)
}

sendFetchRequest()

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

What is the best way to save an integer in HTML's localStorage instead of a string?

I've encountered an issue while using the localStorage feature in a game I'm developing. Specifically, the money variable should be increasing by 1 every second. Here's a snippet of my code: var money = 0; window.onload = function () { ...

Changing return values with Jest mocks in TypeScript

Here I am again with a very straightforward example. In summary, I require a different response from the mocked class. Below is my basic class that returns an object: class Producer { hello() { return { ...

Watching for changes to an object's value in an AngularJS service triggered by a controller from a separate module (Extended Edition)

Referring to this discussion on Stack Overflow: AngularJS trigger and watch object value change in service from controller The original question was about watching for changes in a service from a controller. I am interested in extending this concept to ...

The list countdown for loop only appears in the initial iteration

Hey there, I'm currently facing an issue with duplicating my JavaScript countdowns and displaying images of cards on each loop iteration. Strangely, the countdown only appears in the first instance even though it's within the loop. I'm seeki ...

Having trouble customizing the Material UI button in React?

For a recent project, I utilized the older version (v1) of Material UI to ensure compatibility with Node 10.8. In order to implement a round button, I referred to this demo. The round mini button functioned perfectly without any applied themes. <Button ...

The Google Books API has encountered an authentication error with status code 401

Trying to access public data using the Google Books API locally: An error occurred with the authentication credentials. It seems that an OAuth 2 access token, login cookie, or another valid authentication credential is missing. For more information, visit ...

Accessing data from arrays asynchronously using JavaScript

Update I have included actual code below, in addition to the concept provided earlier. Here is the async array access structure I am trying to implement: for (p = 0; p < myList.length ; p++){ for (k = 0; k < RequestList.length; k++){ i ...

Utilizing requirejs or grunt for concatenation and minification greatly enhances the performance of AngularJS implementations

I'm facing a dilemma with my Angular app. I have several JS files included in the index.html file, and when the app loads, all these files are downloaded before the app is ready. <html> ... <script src="scripts/controllers/loginController.js ...

Has a newly created element been styled or are all values set to default since it is outside of the DOM?

First, I begin by creating an element: let link = document.createElement('a'); After my document is fully loaded and all styles and scripts are applied. The styles may look something like this: a { background-color: salmon; } Therefore, it w ...

What is the best approach in VueJS to implement a skeleton loader and an empty page condition for my orders page simultaneously?

I have implemented a skeleton loader to display while the data is loading. However, I want to also show an empty order page if there is no data or orders coming in. I am trying to figure out the conditions for both scenarios - displaying the loader and t ...

Examining the dimensions of a div element in AngularJS

As I delve deeper into understanding AngularJS and tackling the intricacies of how $watch operates, a specific scenario has caught my attention. I want to monitor and track changes in the dimensions of the div element with an ID of "area". My intention is ...

Tips for configuring Visual Studio Code to utilize path mappings for handling automatic imports

In order to streamline my project and avoid messy paths, I am implementing absolute paths that will allow for consistent imports regardless of the file's location in the project tree. For this purpose, I made adjustments to the tsconfig.json: "paths ...

Guide to accessing URL or parameters in the directory of a NextJs 13 application

Transitioning my getserversideprops() to next13, I am faced with the task of incorporating URL and fetching parameters from the directory structure. In my page path /posts/{postId}, how can I retrieve params or the URL? The code snippet I am currently work ...

Navigate the array and divide the elements into separate values

For a project I need to upload files, wherein the data is organized within an object like [5.76516834507, 50.8474898368], [5.76115833641, 50.8453698247]. The task here is to extract and store the first value as latitude: 5.76516834507 and the second value ...

When converting to TypeScript, the error 'express.Router() is not defined' may

Currently, I am in the process of converting my express nodejs project from JavaScript to TypeScript. One of the changes I've made is renaming the file extension and updating 'var' to 'import' for "require()". However, there seems ...

What steps can I take to avoid keypress events causing issues with the browser's input functionality?

Utilizing Bootstrap's modal component, I have implemented an "Add User" dialog within my web application. In order to streamline the user experience and enable quick data entry, I am aiming for the escape and enter keys to close and submit the form re ...

Converting a JavaScript string into an array or dictionary

Is there a way to transform the following string: "{u'value': {u'username': u'testeuser', u'status': 1, u'firstName': u'a', u'lastName': u'a', u'gender': u'a&a ...

Tips for resolving NPM high severity vulnerabilities related to pollution issues

Every time I attempt to install npm packages, I encounter the same error message indicating "3 high severity vulnerabilities." When I execute the command npm audit fix, I consistently receive this: https://i.stack.imgur.com/3oJIB.png I have attempted to ...

Error: Unable to execute setState in React Native

Why am I receiving an error stating that this.setState is not a function? I'm having trouble understanding why my code isn't working as expected. import React from 'react'; import axios from 'axios' import { StyleSheet, Text ...

Still Facing the 'appendChild' Error Even After Defining it

Looking for assistance in creating new elements to display information on a Discord bot list I'm currently developing. var btn = document.createElement("BUTTON"); btn.innerHTML = "Try It"; document.body.appendChild(btn); ...