Tearing Down an Angular Application

1,741 views
Skip to first unread message

jyoun...@gmail.com

unread,
Nov 8, 2012, 5:33:35 AM11/8/12
to ang...@googlegroups.com

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 the widgets. So, basically we need to tear down an angular application safely, without any leaks...

As angular doesn't appear to have an "official" mechanism for tear down (Issue 1537), 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.

It would seem that the angular way to do this would be for services that attach to global events (such as browser) should attach to the $rootScope's $destroy event. However, $rootScope currently ignores $destroy calls. An alternative would be to use the mechanism above to support an $injector.destroy() which cascades to all of its services.

There are interesting issues to consider regardless, for example, what if service A utilizes service (B) during its destroy and B has all-ready been destroyed? This could potentially be managed by inspecting the dependency tree, however, manual resolutions through "get" would fail. Alternatively a two phase tear down may alleviate these issues (but would require developers to understand the cycle), yet another alternative would be to say fine, use B, its unhooked from anything global, and will just return you default responses.

I need a solution for our application so will be forking the source, so some feedback would be good, as I'd like to consider putting together a proper solution that can be shared :)


Message has been deleted

jyoun...@gmail.com

unread,
Nov 8, 2012, 5:45:50 AM11/8/12
to ang...@googlegroups.com, jyoun...@gmail.com
More thoughts...

Conceptually, what we are doing is inverting our dependencies on subscriptions to global events, this is the only reason Browser is leaking. If all events where subscribed to via a service that inverted our dependencies on the target object, the only object we would have to cleanup would be the service object managing our events. In all other respects angular is pretty clean, with everything being managed within the injector.

Hope that makes some sense :)

Misko Hevery

unread,
Nov 8, 2012, 6:15:02 AM11/8/12
to ang...@googlegroups.com, jyoun...@gmail.com
This is a good idea. In the meantime, I am thinking how we could help you work around this issue. I think you should override the Browser instance and provide your own. You could then share the overridden instance across all of the application instances, and you could then use your own Browser to clean up. 


--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular?hl=en.
 
 

jyoun...@gmail.com

unread,
Nov 8, 2012, 6:32:27 AM11/8/12
to ang...@googlegroups.com, jyoun...@gmail.com, mi...@hevery.com
Interestingly we have our own IoC container within our widget framework that we use to expose widget scoped services in a framework agnostic way (some within the organization are still stuck in the dark ages, writing widgets in backbone) :) We flow these services through to angular, therefore by implementing Browser in our widget framework with a corresponding "dispose" method we get a clean abstraction + the automatic cleanup already applied in our framework. Sounds pretty clean, and means I can remove the temporary hack I added to Browser :)

Ben Wiklund

unread,
Sep 13, 2013, 1:50:46 PM9/13/13
to ang...@googlegroups.com, jyoun...@gmail.com, mi...@hevery.com
Has there been any movement on this in the last year? We're working on a similar project and would love to have a supported method for destroying apps.

John Reading

unread,
Nov 14, 2013, 5:35:29 PM11/14/13
to ang...@googlegroups.com, jyoun...@gmail.com, mi...@hevery.com
I'm also hitting this one rather hard. 

I'm trying to destroy scope after the element is removed from outside angular. Currently using angular.bootstrap to load module apps to elements in GWT. Seems angular.element($('#myNGModuleApp')).scope() is just a copy of the scope. I can kill that, but timers, functions, etc. all still exist in a closure.

Anyone working on this?

John

Misko Hevery

unread,
Nov 15, 2013, 2:38:25 AM11/15/13
to John Reading, ang...@googlegroups.com, jyoun...@gmail.com, mi...@hevery.com
Have you tried scope.$on('$destroy', ...)?

Ben Wiklund

unread,
Nov 15, 2013, 3:09:49 AM11/15/13
to ang...@googlegroups.com, John Reading, jyoun...@gmail.com, mi...@hevery.com
Is that sufficient to tear down an entire angular app? In our particular use case, we truly want to have separate widgets on the page that live entirely in their own worlds, and can be instantiated and torn down at will.

Our use case is: support potentially hundreds of widgets that we don't want to load initially, swap them in and out, and destroy them. Currently the only acceptable solution has been iframes, but obviously that doesn't scale with dozens of widgets. I talked with Vojta at a meetup recently, and there was talk about refining how modules work, but thats as much as I know.

Personally, I'd love a way to manage the $digest process in a fine-grained way, just like we can manipulate scope. We have a large team of people working on widgets, and if one widget is super expensive on digest, we could get around that by sectioning off areas of the app to their own digest, with the knowledge that triggering a 'global' apply is something that should be done manually. The problem arises with $http, $timeout, ng- handlers, and others that always fire an $apply on $rootScope.

Perhaps we could wrap those services in something that accepted a scope to call $digest on, we could sort most of that out, but that would be a big scary fork from the main angular repo, so we haven't gone there yet.

Thanks!


--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/_AulBSlrspU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.

To post to this group, send email to ang...@googlegroups.com.

Josh Ponelat

unread,
Jul 15, 2015, 3:07:49 AM7/15/15
to ang...@googlegroups.com, jyoun...@gmail.com
Has a best practices for destroying an angular app been established ?

If I bootstrap and angular app onto an element.
How would I go about un-bootstrapping it?

...Would I just call $destroy on the $rootScope then remove the element from the DOM? 

There are quite a few things I'm not familiar with (the internals). I'm trying to catch up with this thread (and another on github).
So thanks for any pointers!
Reply all
Reply to author
Forward
0 new messages