Open deepxg opened 8 years ago
This is an interesting question. There is the capability in cljs-ajax and goog.XhrIO to abort requests, the question is how to do this with re-frame. One possibility is that users specify an additional :id
key, and we create a new fx
called :abort-http-xhrio
which takes ids to cancel.
Or would it be better to have an API that allowed a programmer to specify some sort of identifier for each request, such that multiple requests with the same identifier caused the previous one to abort?
This is an interesting idea which could simplify some kinds of code, like debouncing search results.
Yeah, purely for debouncing I often have code like this:
(reg-event-fx
:app/store-debounced-event
(fn [{db :db} [_ event timestamp]]
{:db (assoc-in db [:app/debounce (first event)] {:timestamp timestamp :event event})}))
(reg-event-fx
:app/dispatch-debounced-event
(fn [{db :db} [_ event timestamp]]
(let [{latest-timestamp :timestamp event :event} (get-in db [:app/debounce (first event)])]
(if (= timestamp latest-timestamp)
{:db (update db :app/debounce dissoc (first event))
:dispatch event}))))
(reg-event-fx
:app/debounce-event
(fn [{db :db} [_ event]]
(let [timestamp (.getTime (js/Date.))]
{:dispatch [:app/store-debounced-event event timestamp]
:dispatch-later [{:ms 500 :dispatch [:app/dispatch-debounced-event event timestamp]}]})))
Which is easy to wrap in an effect handler. But I suspect there's a more general case, as I'll often want to kill off slow requests when navigating. There's even perhaps a wider (re-frame) point that currently effect handlers aren't that extensible, because they expose no data themselves - in this case it would be good to get a map out of all the current requests, so you could handle aborting requests without having to inspect or copy the actual implementation of http-fx.
i need this functionality too, and for me would be better to have something like :on-request [:my-event]
, where request object will be passed, easiest and flexible way i think
@danielcompton what do you think? can i make a PR?
I just came here looking for the same reason. I have some very long running queries, and currently I manually build the requests for those using the re-frame-http-fx plumbing (just so it looks the same). I'm refactoring and wanted things to be consistent and hit the two spots where I use (ajax/abort req)
and just realized I'm falling short.
My gut says @flexsurfer's :on-request
is a starting point that is definitely good enough.
The dispatcher can then decide what to do with the raw request, save it in the app-db
and then manipulate it later. One caveat is that some cleanup needs to happen in both :on-success
and :on-failure
, but that is up to the caller and should be documented clearly.
Hi. I was thinking about it and maybe two additional keys could be added to the event?
:id
- id under which request would register possibly inside some local atom when started and unregister when completed. If second request with the same id would come along before first one would finish, first one would be aborted.
:when
- predicate taking db and returning bool (e.g. (fn [db] (= (:page db) :user-list)
). This predicate would say if request is still valid (user is still on the page, search query didn't change...) and if it returns failse
, events shouldn't be triggered even if response arrived.
Ideally when event is in progress and :when
condition changes, request should be immediately aborted. Only way to do this now is probably by attaching watch on the app-db
atom?
I could send pr if this is acceptable.
It's common to want to abort an in-progress HTTP request, perhaps if a more recent request comes along (for example the case of multiple autocomplete requests), or if the user navigates away and it is no longer relevant.
How might I go about holding on to handlers (perhaps in
:db
) so that I can later handle them? Or would it be better to have an API that allowed a programmer to specify some sort of identifier for each request, such that multiple requests with the same identifier caused the previous one to abort?