Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does never resolved promise cause memory leak?

I have a Promise. I created it to cancel an AJAX request if needed. But since I don't need to cancel that AJAX, I've never resolved it and AJAX completed successfully.

A simplified snippet:

var defer = $q.defer(); $http({url: 'example.com/some/api', timeout: defer.promise}).success(function(data) {     // do something });  // Never defer.resolve() because I don't need to cancel that ajax. What happens to this promise after request? 

Do never resolved promises like that cause memory leaks? Do you have any advice about how to manage Promise life cycle?

like image 336
Umut Benzer Avatar asked Nov 19 '13 10:11

Umut Benzer


People also ask

What is the main cause of memory leaks?

In general, a Java memory leak happens when an application unintentionally (due to logical errors in code) holds on to object references that are no longer required. These unintentional object references prevent the built-in Java garbage collection mechanism from freeing up the memory consumed by these objects.

How do you prevent a memory leak in closure?

Only capture variables as unowned when you can be sure they will be in memory whenever the closure is run, not just because you don't want to work with an optional self . This will help you prevent memory leaks in Swift closures, leading to better app performance.

Does exit cause memory leaks?

Not under modern operating systems, no. The OS automatically collects all the memory when the process dies. In fact freeing memory can actually be detrimental for the performance if the program is exiting anyway.


1 Answers

Well, I'm assuming you don't keep an explicit reference to it since that would force it to stay allocated.

The simplest test I could think of is actually allocating a lot of promises and not resolving them:

var $q = angular.injector(["ng"]).get("$q"); setInterval(function () {     for (var i = 0; i < 100; i++) {         var $d = $q.defer();         $d.promise;     } }, 10); 

And then watching the heap itself. As we can see in the Chrome profiling tools, this accumulates the needed memory to allocate a 100 promises and then just "stays there" at less than 15 megabyes for the whole JSFIddle page

enter image description here

From the other side, if we look at the $q source code

We can see that there is no reference from a global point to any particular promise but only from a promise to its callbacks. The code is very readable and clear. Let's see what if you do however have a reference from the callback to the promise.

var $q = angular.injector(["ng"]).get("$q"); console.log($q); setInterval(function () {     for (var i = 0; i < 10; i++) {         var $d = $q.defer();         (function ($d) { // loop closure thing             $d.promise.then(function () {                 console.log($d);             });         })($d);     } }, 10); 

enter image description here

So after the initial allocation - it seems like it's able to handle that as well :)

We can also see some interesting patterns of GC if we let his last example run for a few more minutes. We can see that it takes a while - but it's able to clean the callbacks.

enter image description here

In short - at least in modern browsers - you don't have to worry about unresolved promises as long as you don't have external references to them

like image 90
Benjamin Gruenbaum Avatar answered Oct 12 '22 13:10

Benjamin Gruenbaum