Vishnu Vishnu - 3 months ago 34
Ajax Question

Huge Memory Leaks with XMLHttp POST Request

How can i avoid XHR POST Memory leak? I go through lots of web pages regarding XHR memory leak but there is no good solutions. My problem is almost similar to this That blog explains the problem but no solutions.

My Problem:
I have a web app which Continuously send date to server (2Mb to 80Mb) and it will make 10 to 300 requests. It is POST request. for GET request no big problem like this.

How can i solve this?
Circular reference, Scope , closer etc i try but no success.
i try to use delete keyword for readystate change, delete previous xhr object , try to reuse xhr , xhr reference to null , changing coding patters etc

This is the sample code. this is the functionality i need

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 accomplish this without Memory leaks?

Answer

for every request you send, you add a new onload handler.

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

The old handler will not be deleted at this point and stays in memory. The garbage collector will not be able to free the memory.

In your case you only ever need one eventlistener, so i recommend moving the attachment of the listener out of the sendRequest function like so, and the memory leak should be gone.

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

EDIT: Version 2

i have tried another version which produces even better results. memory never surpasses 2.6G on my setup. Its a derivation of Jaromandas work. It's basicly his version with an 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 ();