chaplinjs / chaplin

HTML5 application architecture using Backbone.js
http://chaplinjs.org
Other
2.85k stars 231 forks source link

Controller dispose not called if beforeAction still pending #752

Open brianensink opened 10 years ago

brianensink commented 10 years ago

Hi,

I have found a scenario where a controller's dispose method is not called however I believe it should be called.

The setup:

  1. The user causes a navigation to "controllerA#action"
  2. The controllerA beforeAction method returns a pending promise
  3. The user causes a navigation to "controllerB#action" while the promise is still pending

The dispatcher will correctly create controllerB and invoke the action method, however the controllerA instance is lost and never disposed. The pending promise may eventually be resolved (or rejected) and execute application specific behavior. If controllerA was disposed then the application logic could check the disposed flag when the pending promise is finally resolved in the beforeAction method.

In my specific situation I am calling a slow server API from the controllerA beforeAction method. The user can click a "Cancel" button (step 2 above) and immediately go to another page. However the slow server call is eventually resolved and my application specific logic causes unexpected things to happen.

I can use other means to fix my application problem however my first attempt was to check this.disposed and I discovered that the controller was never disposed.

Sija commented 10 years ago

@brianensink try my fix branch and see does it resolves your issue

brianensink commented 10 years ago

@Sija No it does not fix my issue. It disposes the controller after the promise is rejected but at that point it is too late for me. I have error handling code in beforeAction that redirects. If the controller was disposed as soon as a newer controller was created then I could use the disposed flag to skip my error handling.

I think the problem is more general and the correct behavior is a design choice. What should happen if Chaplin is asynchronously routing to one action method when some event happens and causes Chaplin to route to a different action method instead? How should Chaplin "interrupt" the first routing and how should the application controller know that it was interrupted?

I thought I could use the disposed flag for this but maybe a different flag is better to indicate that the action was interrupted while waiting for a promise.