angular-ui / bootstrap

PLEASE READ THE PROJECT STATUS BELOW. Native AngularJS (Angular) directives for Bootstrap. Smaller footprint (20kB gzipped), no 3rd party JS dependencies (jQuery, bootstrap JS) required. Please read the README.md file before submitting an issue!
http://angular-ui.github.io/bootstrap/
MIT License
14.3k stars 6.74k forks source link

memory leak with modal window #6579

Open squarewave24 opened 7 years ago

squarewave24 commented 7 years ago

hi, I've read all the past issues and I see this has been fixed a while ago, but I am having this issues with v2.5

I've done some memory snapshots in chrome, and i see hundreds of detached modal windows starting with following markup:

<div class="modal app-modal-window fade ng-scope ng-isolate-scope" role="dialog" style="z-index: 1050; display: block;" tabindex="-1">

here is my open/close logic:

$uibModal.open({
            templateUrl: '...',
            controller: controllerName,
            windowClass: 'app-modal-window',
            controllerAs: 'vm',
            resolve: {
                position: position,
                screenConfig: () => screenConfig // need this otherwise DI kicks in on strings..
            },
            size: 'lg'
        }).result;

close:

this.$uibModalInstance.close();

is there a way to properly dispose them?

The other option is that within the modal, something gets assigned that links to angular scope/controller and that link is not being released? although i went through the code and don't see anything obvious so far.

 * angular-ui-bootstrap
 * http://angular-ui.github.io/bootstrap/
 * Version: 2.5.0 - 2017-01-28
jacobmassengill commented 7 years ago

I am having this issue as well, on a much earlier version. It appears to be a flaw by design of angular, and have found no solutions as of yet.

maufarinelli commented 6 years ago

I have the same problem in our app. So, I tried in the https://angular-ui.github.io/bootstrap/#!#modal After opening and closing 17 times the modal in angular-ui page, that is what I see: uibmodal-leak Clearly we can see increasing Nodes and Listeners

squarewave24 commented 6 years ago

I think it comes down to the code running in the window. but if you find any bugs with the Modal UI that would be a bonus :)

you have to ensure that the model can be disposed when the window is closed. If some of your objects have root links, those objects will not be disposed.

i've been going through code and removing any suspect code that could introduce links like events with no unsubscribe, timers, writing to console window etc.. more common pitfalls here:

https://makandracards.com/makandra/31289-how-to-create-giant-memory-leaks-in-angularjs

daniel4wong commented 6 years ago

I found that if the modal template has a button, and you once clicked the button (to close the modal or not), memory leak will happen.

I have tried that if I open the dialog, and call below script to close the dialog in console, there is no memory leak. angular.element(document.querySelector('.modal')).scope().$close()

I still finding why...

leolux commented 6 years ago

Which version of angularjs do you use while facing this issue?

nicolashery commented 6 years ago

We've been having memory leaks on an Angular 1.5.11 application, and I think I've narrowed it down to being the Modal.

This recording was taken on the docs website, by just opening & closing the modal ~20 times. Looks like something is preventing listeners/DOM nodes from being cleaned up:

screen shot 2017-12-21 at 2 26 52 pm

Update: Clicking "Collect Garbage" at the end of the recording actually brought it back down, so might not be a memory leak:

screen shot 2017-12-21 at 2 57 12 pm
texiontech commented 6 years ago

I have the same issue that will be occur when clicking on the link or button with call function on the components

clhma commented 6 years ago

I have the same issue with version 1.3.2 and angular 1.5.5. I found that the memory leak was due to the following code:

$compile(backdropDomEl)(backdropScope);
$animate.enter(backdropDomEl, appendToElement);
...

$animate.enter($compile(angularDomEl)(modal.scope), appendToElement);

$animate.enter creates a key in an internal map (activeAnimationsLookup):

$compile will compile the element 'asynchronously' (so after $animate.enter). So angular will change the domElement INSIDE the jqlite wrapper with a new $$hashKey! => that's why $animate is not enable to clear its internal map because the $$hashKey has changed...

So to fix the memory leak, I changed this code to remove the animation:

   $compile(backdropDomEl)(backdropScope);
   // $animate.enter(backdropDomEl, appendToElement);
   appendToElement.prepend(backdropDomEl);
  ...
   // $animate.enter($compile(angularDomEl)(modal.scope), appendToElement);
   appendToElement.prepend($compile(angularDomEl)(modal.scope));

Doing this, I loose a css animation (not used in my project) but the main animation of the modal is still working.

I saw that this code is still present in the current version of angular bootstrap so maybe your memory leak has the same cause.

Hope this helps.