angular / angular.js

AngularJS - HTML enhanced for web apps!
https://angularjs.org
MIT License
58.82k stars 27.51k forks source link

Destroying an angular app #7578

Open shahata opened 10 years ago

shahata commented 10 years ago

I've been playing around this weekend with a project that I've been meaning to open source for a while now: https://github.com/shahata/angular-widget

In a nutshell, it let's you create many "widgets" in a single page, each widget is lazy loaded and has it's own injector and all of them live together nicely in one page. Demo at: http://shahata.github.io/angular-widget/#

When you click "add..." a widget is added, and when you click "del" it is destroyed. I'm no performance expert, but if I look in developer tools I see that destroyed widgets are cleaned up nicely.

The problem is, that if I add a "bad" widget it does not get cleaned up so nicely. What's bad about this widget? Well, it uses $cookies. $cookies polls the browser's cookie storage every 100ms to check if cookies were updated. It start to poll when it is created and stop... well, never. So if I add many "bad" widgets, I have many polling timeouts of $cookies and even if I remove all the widgets polling continues, and I guess also prevents GC.

I would like to try and add a mechanism for destroying angular apps in order to deal with this kind of issues. If this is something desirable for angular, I can take this PR. The design I have in mind is that users will be able to call injector.$destroy() and the injector will then call $destroy on every injectable that has a $destroy method which in turn will cancel any pending actions like timeouts, intervals, http requests, etc.

$rootScope obviously already has a $destroy method, though it is a bit partial - see https://github.com/angular/angular.js/pull/7564

shahata commented 10 years ago

Here is what the devtools look like after adding many "regular" widgets and then removing them (good) and then adding many "bad" wodgets and then removing them (not so good):

perf

thebigredgeek commented 10 years ago

I personally think angular-cookies needs a massive refactor. Honestly, we should be using getters/setters instead of constant polling. This is a huge waste of battery life on mobile. And the new direction is Mobile First!

caitp commented 10 years ago

@thebigredgeek please direct your attention to Angular v2.0.0 for all your mobile-first needs, that's really the place where we can rely on ES5 at least existing

shahata commented 10 years ago

Just to make sure there is no confusion - this issue is NOT about cookies and NOT about mobile. It is about destruction of apps/injectors.

btford commented 10 years ago

@shahata the problem is that all 3rd-party services would also potentially need to implement this.

For your case, I think a pragmatic approach would be to roll-your-own cookies service that doesn't involve polling.

Angular 1.x currently doesn't have a way to destroy services. I don't think there's a good way to add this type of feature that's aligned with the current Angular app lifecycle.

shahata commented 10 years ago

@btford yes, this is similar to how we expect directives to element.on('$destroy', ...) if they have any cleanup to perform. I think we can expect services to implement a $destory method if they need to cleanup.

btford commented 10 years ago

@shahata do you have any other specific services that poll?

I think this idea is interesting, but my gut feeling is that it's going to be more trouble than it's worth.

See also #6180.

shahata commented 10 years ago

@btford I have many "widgets" written for this angular-widget framework and I'm pretty sure polling will be required for some of them. Since we currently develop widgets only internally I can probably workaround this with some patch, but I think it is better to solve this the proper way.

If you think that it is interesting, I will send a PR for this. Otherwise, probably not a big deal.

thebigredgeek commented 10 years ago

@shahata you can't simple use events?

shahata commented 10 years ago

This will probably be solved by https://github.com/angular/angular.js/pull/8005

gkalpak commented 8 years ago

(FWIW, $cookies no longer use polling - but I understand this is not about $cookies :smiley:)