-
Notifications
You must be signed in to change notification settings - Fork 27.5k
$destroy on rootScope is ignored #1537
Comments
Can you provide a test that shows this (not) happening? |
Indeed, the As for the element |
I need to do some more digging, however I'm not convinced that broadcasting a destroy is the correct approach as it does not actually call destroy on the scope, e.g. it doesn't unlink it from siblings, parents, $digest cycles, etc. It simply broadcasts the message...., alternatively...
|
If you look at the
Since the |
OK, after some more investigation calling $destroy to tear down angular is currently flawed, ngInclude, etc. don't subscribe to $destroy. The correct way (I believe) to tear down the application is to structure it in such a way that you can effectively clear the model data bound at the root, e.g. rootScope.model = null, and let all the standard directives cascade. All other mechanisms detailed above leak (and badly).... |
OK so first of all why would you want to destroy the rootscope? ... sent from my tablet
|
What I want to do (as stated in the original question), is understand the correct way to tear down an angular based application. We have an application made up of "widgets" that are loaded dynamically (via require), each widget is a separate angular application (via manual bootstrap), we need to be able to un-install widgets. So, basically we need to tear down an angular application safely, without any leaks... I "don't" expect $destroy to do this for me, and after looking at the code the other suggestions above seem naive (sorry guys). |
Right. So you are manually bootstrapping a load of angular apps and you From looking at the code (rootScope and injector) it seems that all var injector = createInjector(modules); Then attach this injector to the DOM element data property element.data('$injector', injector); and finally compile up the element with the a new Scope, which is the compile(element)(scope); At no point does anything get added to the global namespace. It is all If so then it is probably something for Misko, Igor or Vojta to take a look Pete On 7 November 2012 16:31, Jason Young notifications@github.com wrote:
|
Pete, thanks for looking into this for me, I do appreciate the efforts :) To be honest, I wasn't going to even post the issue, as I knew what the score was after looking at the code myself...(but I was convinced by a colleague that I might have missed something). Anyway, we've still got leaks in our current implementation, even after striping things back, but only if we use certain angular features (so it seems). The one thing I need to do this morning is remove our "widget" framework completely from the picture and see where I am with a pure angular solution. Once I've done that I'll post my findings here for others, and if I track the issue I'll submit a pull request... |
OK, back to my original post here I think. As angular doesn't appear to have an "official" mechanism for tear down, there is no way to tell the injector to dispose of all of its services, therefore, services such as browser which attach to window events have no idea that they should detach their event handlers, this leads indirectly to the root scope being held onto. In our "widget" framework, when we destroy our context (which is similar to angular's injector), the context's lifetime container calls dispose on any services we are managing (if they support it), allowing them to perform cleanup. This is what I believe is required to make angular support application tear down. I'm going to do more investigation into this, but the retaining object tree in chromes memory profile is pretty conclusive... I'll post further finds as I encounter them. |
The leak is fixed, although the solution is hacky at the moment. I still believe an application tear down mechanism is required, however, this is a complicated issue which will require some thought. Firstly, get the root of your application to use an ng-include (for applications that add/delete nested angular applications, this is probably your development model anyway), by setting the Url to null you can get angular to clean up pretty much everything for you. In addition to this you need to then remove your application root node (calling cleanData is not enough) and get the browser object to unhook its events.
Code added to browser object
As I say, not pretty, but for anyone else needing a temporary solution this could help.... |
@suedama1756 I wonder how did your approach change based on this comment: |
I have the same issue bootstrapping ng apps in GWT and removing those elements from the DOM. App still exists in memory although |
I would like to vote up this issue, as for my app it is very important to make the angular application recyclable. So either allow reattaching the application scope to the same DOM element, or introduce some destroy method. The 1.2 version of Angular disallows all the previously possible ways! It's a no-go! Thanks for your consideration. |
has this been fixed by #5279 @petebacondarwin @czechdude @suedama1756 ? |
@suedama1756 et al - can you confirm if #5279 (and other related leak fixes) solves your problems? If not, please comment pinging me. I am going to close this issue for now. If you can provide a specific example of an issue that is not fixed by these changes then please create a new issue. |
I am looking for same kind of solution want to clear scope data on tab close , i didn't find any solution to broadcast an event for $destroy scope |
It is not clear what you want @tkssharma - you can listen to a |
Hi everyone, quick question kind of related to this, is there a way to either destroy a custom injector or use it as default during the bootstrapping process? Basically i'm stopping angular's bootstrapping process in order to do some one-time only requests that i need before the app starts and then i resume it. Currently i'm doing those requests outside of angular, i thought about generating a manual injector in order to handle those requests through angular services but i don't like the idea of having two injectors once the app is finally bootstrapped. |
@HeberLZ, there is currently no way to destroy an injetor. Maybe you can let it be garbage collected if you don't need it anymore. Essentially, you can create as many injectors as you want, using You just need to be careful when instantiating services that have "permanent" side-effects on the page (e.g. adding a listener on window or document etc). I think your best bet would be to call function doSomethingBeforeBootstrapingMyApp() {
// Create an injector
var myTempInjector = angular.injector(['ng', 'someModule']);
// Instantiate a service and use it
var SomeService = myTempInjector.get('SomeService');
SomeService.doSomething();
// Clean up
var $rootScope = myTempInjector.get('$rootScope');
$rootScope.$destroy();
} Btw, GitHub issues are reserved for bug reports and feature requests. You can use one of the general support channels for these types of questions. |
Good day everyone and @petebacondarwin, sorry to bother everyone. I'm reading the documentation website. It does not have a documentation about this way of disposing the angular.bootstrap app. How do I add the following documentation to the angularjs website: where should i add that from below? edit: assuming i will be following the design guidlines not using states outside the scope of each angular.bootstrap compiled elements. If i have many angular.bootstrap elements, their behaviours will be independent right? Meaning each injections and linkers does not share any state? I will also add the last question to the documentation |
It has been a while since I have looked at this stuff, but I am not sure that simply removing the bootstrapped element is enough to actually clean up the application... |
@petebacondarwin thank you for the response. sorry to bother you again. Is https://angular-ui.github.io/ under angularjs.org (the official ui class like https://material.angular.io/ for https://angular.io/) or a 3rd party team/project? how come it is not included or even mentioned in https://angularjs.org/ ? |
AngularUI is a 3rd party project |
Hi,
$destroy on root scope is ignored. In addition to this, scopes do not appear to go through a $destroy cycle when their corresponding element is destroyed, e.g. they do not subscribe to element.$destroy and forward this on to scope.$destroy. This is a problem as custom directives tend to subscribe to scope.$destroy to perform clean-up rather than element (although you could argue they should). This makes it quite difficult to tear down an angular based "widget" or application. With the ability to manually bootstrap an angular application, it would be great to also have the ability to tear down.
In my case I've got some clean (ish) ways of working around the issue, but would appreciate any suggestions...
The text was updated successfully, but these errors were encountered: