Summary:
We run into the following situation with our Ember app and are struggling to find an appropriate solution.
We are dealing with a lot of data and hence some of our requests for data are rather slow.
Initially we used Em.RSVP.hash to "bundle" our requests in the model hook of each route. However this would lock up the UI and was ultimately not acceptable.
Our solution was to cascade the requests in the setupController hook like so:
setupController: (controller, model)->
slowRequest1WhichReturnsAPromise().then (data)->
# Do something with request 1 data
slowRequest2WhichReturnsAPromise().then (data)->
# Do something with request 2 data
slowRequest3WhichReturnsAPromise().then (data)->
# Do something with request 3 data
This works. We get instant page load and can show the most relevant data first.
We try to keep Ember up to date (1.11.3 at the time of writing). We are not using Ember Data.
The Problem:
The problem is that the UI is unlocked. The user can, for example, logout (and be redirected to the login page). The requests persist and eventually complete, messing up the csrf token which we set on login and logout. The next time the user tries to login they get a 422 error.
An even simpler scenario is changing a filter setting before the long running requests finish. New requests (often reduced in scope by the filter change) finish before the initial requests. Data then gets overwritten by the eventually finishing original requests.
Our immediate solution was to try and kill the pending promise but cannot find a "modern" way to do it.
This works:
allPromises: []
setupController: (controller, model)->
deferredRequest1 = new Em.RSVP.defer()
# Store all promises
@get('allPromises').pushObject(deferredRequest1)
# Fire off request 1
# Spark up the next stage when request 1 finishes
deferredRequest1.promise.then ->
deferredRequest2 = new Em.RSVP.defer()
@get('allPromises').pushObject(deferredRequest2)
# ...
actions:
signOut: ->
@get('allPromises').forEach (promise)->
promise.reject('canceled')
The above is a bit ugly and simplified to get the point accross.
Ember Docs state that "New code should use the RSVP.Promise constructor instead (of defer)". However there seems to be no way to do this using the new way.
Questions:
Is there a modern way to cancel pending promises / requests?
Is there a better way to split up our page load to enable a clean way to cancel pending requests?
Update
I ended up using the defer. It's not beautiful, but will do till we refactor the UI and perhaps rethink the need for the slow queries.
Thank You.