JQuery memory leak suspicion

I am making an AJAX request for XML. I do it every second. I notice that my memory usage is growing at hundreds of megabytes. As you can imagine, the client is not satisfied. After some readings in different places, I suspect that closing functions causes my headache. I am looking for any verification that can be provided, as well as any help in resolving it.

function PageManager () { var self = this; self.timeoutHandler = function () { $.ajax ({ url: 'URLtoXML', type: 'post', cache: false, context: self, success: function (data) { var slf = this; var xmlDoc = $($.parseXML (data)); xmlDoc.find ("tag_label").each (function () { self.val = parseInt ($.trim ($(this).text ())); } setTimeout (slf.timeoutHandler, 750); } }); } } var pm = new PageManager (); pm.timeoutHandler (); 

EDIT . I have included some ideas from people and some of the internal elements of the success handler. I see lower growth rates, but not by much.

+6
source share
4 answers

To avoid the fact that any newly created function (context) is closed above the parent area here, you just need to get rid of the anonymous function in setTimeout . So

  setTimeout(self.timeoutHandler, 750); 

However, even if this closure covers the context of the parent (s), any semi-decent garbage collector (like any modern browser) will notice it and free up memory after this method has been run. A very important thing that you did not mention is the browser on which you noticed the behavior. The Firefox garbage collector, for example, works .. quite unpredictable (at least for me). This will allow more and more memory to be used, and then at some point will release a huge chunk again.

To find out what’s going on, use Firefox and look at about:memory while the script is running. There you will see where the memory goes. I would not worry if memory usage grows for a while. Look at this, if this is all your code, memory should be freed sooner or later.

+6
source

Memory grows when you keep links to things. This is a leak when you accidentally do it.

In this case, your timeoutHandler function calls itself, and again and again ... It will never be able to clear the call stack. I bet it's your leak.

To avoid this problem, use setInterval . It works just like setTimeout , but it will call the function every milliseconds until you clear it with clearTimeout (or until the world ends).

The downside is that you cannot do this quickly, your current implementation always waits 750 milliseconds after each call. I suppose you could do something fantastic that would still allow you to have a good time (using Date to check the time), but that’s not what I could write in 10 seconds: P

0
source

I'm just going to drop my two cents, but I agree with jAndy (+1). However, I would generate one linked callback once, instead of creating a new closure on any iteration of the callback (which could theoretically keep the volume and xml data alive much longer than you want. I would suggest another alternative, this is:

 function PageManager () { var callback = (function(self) { return function() { self.timeoutHandler(); }; })(this); // only one callback this.timeoutHandler = function () { $.ajax ({ url: '/echo/json/', type: 'post', cache: false, data: {a:Math.random() }, success: function (data) { //var xmlDoc = $($.parseXML (data)); // Processing of XML //alert("data"); setTimeout (callback, 750); } }); }; } var pm = new PageManager (); pm.timeoutHandler(); 

Edit

Here is jsFiddle with the code above, and I watched memory management for a while, but not enough to be convincing in any sense.

0
source

Timeout function

 setTimeout(self.timeoutHandler, 750); 

may cause a memory leak. Although success: the callback may exit after completion, there may not be an empty context in the setTimeout callback causing a circular loop. Youl should take out an anonymous function so that it ends up with something like this:

 var pManager = new PageManager (); pManager.timeoutHandler(); function PageManager () { var ret = (function(self) { return function() { self.timeoutHandler(); }; })(this); this.timeoutHandler = function () { $.ajax ({ url: '/echo/json/', type: 'post', cache: false, success: function (data) { setTimeout (ret, 750); } }); }; } 

It only needs to be called back once.

0
source

Source: https://habr.com/ru/post/902869/


All Articles