I''m looking for a good pattern that prevents AJAX requests from overlapping. Consider this scenario, using an address book application as an example: 1. On the left side of the page, there''s a list of contacts. On the right side, there''s a box that shows the currently selected contact. (Only one contact can be open at a time.) 2. The user clicks on a contact to open it. 3. The app initiates an AJAX request, but it takes a while. Maybe the server has to do some extra processing for some reason. 4. The user gets impatient, and clicks on another contact before the first one has loaded, which initiates a second, parallel AJAX request. 5. The second contact loads immediately, and the user starts working with it, but then... 6. ...the first AJAX request finally completes, and the first contact gets loaded over the second! Obviously, the first AJAX request should be canceled if a second request of the same type is issued while it''s still running. Here''s what I''m thinking: a generalized utility class - say, SerialRequestManager - designed to handle all situations of this type. Sort of a wrapper around Ajax.Request. A setRequest() method would accept an Ajax.Request object (and, if one is already set, destroys the existing one first); you''d probably want a cancelRequest() method, as well. The same class could hide and show an activity indicator. To stray from the original problem a bit: a variant class - ParallelRequestManager - could add incoming requests to a queue, rather than destroying existing ones; it would show the activity indicator when the first request was added to the queue, and hide it when the last remaining request in the queue completes. Does any of this sound sensible? :) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Well, it does sound quite sensible, if not a bit heavy for your specific problem (which, by the way is not rooted in the transport layer, but in the UX layer... the user experience). The crux of your problem is that the user is clicking something again. Why? Because he is unaware that anything is going on from the first click (i.e. your request is taking longer than the user expects and you give no indication that something is happening). The most common pattern, which for all intents and purposes works and is far less complicated to implement than the "request queue", is to implement a "Loading..." shim that renders everything underneath it unclickable, and goes away when the call returns. Now... if you''re hellbent on implementing the "request queue"... let me know and I''ll offer up some suggestions (we have done something similar for other issues). BUT, the answer I gave above is IMHO a more accurate solution if you objectively look at the real issue. On Tue, Jul 1, 2008 at 7:18 PM, Travis Miller <greenie2600-/E1597aS9LQAvxtiuMwx3w@public.gmane.org> wrote:> > I''m looking for a good pattern that prevents AJAX requests from > overlapping. > > Consider this scenario, using an address book application as an example: > > 1. On the left side of the page, there''s a list of contacts. On the right > side, there''s a box that shows the currently selected contact. (Only one > contact can be open at a time.) > 2. The user clicks on a contact to open it. > 3. The app initiates an AJAX request, but it takes a while. Maybe the > server has to do some extra processing for some reason. > 4. The user gets impatient, and clicks on another contact before the first > one has loaded, which initiates a second, parallel AJAX request. > 5. The second contact loads immediately, and the user starts working with > it, but then... > 6. ...the first AJAX request finally completes, and the first contact gets > loaded over the second! > > Obviously, the first AJAX request should be canceled if a second request of > the same type is issued while it''s still running. > > Here''s what I''m thinking: a generalized utility class - say, > SerialRequestManager - designed to handle all situations of this type. Sort > of a wrapper around Ajax.Request. A setRequest() method would accept an > Ajax.Request object (and, if one is already set, destroys the existing one > first); you''d probably want a cancelRequest() method, as well. The same > class could hide and show an activity indicator. > > To stray from the original problem a bit: a variant class - > ParallelRequestManager - could add incoming requests to a queue, rather than > destroying existing ones; it would show the activity indicator when the > first request was added to the queue, and hide it when the last remaining > request in the queue completes. > > Does any of this sound sensible? :) > > > > > > >-- Ryan Gahl Manager, Senior Software Engineer Nth Penguin, LLC http://www.nthpenguin.com -- WebWidgetry.com / MashupStudio.com Future Home of the World''s First Complete Web Platform -- Inquire: 1-920-574-2218 Blog: http://www.someElement.com LinkedIn Profile: http://www.linkedin.com/in/ryangahl --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Yes, very important to show immediate feedback so the user knows what''s going on; shocking how often that isn''t done. In many cases, just that alone is going to prevent the OP''s scenario with the impatient user. But unless it''s unavoidable/inappropriate, I''m not a fan of that preventing other actions. The number of times I''ve clicked the wrong thing and been frustrated because I couldn''t do what I wanted to do until the thing I didn''t want to do finishes... So my take is: Offer immediate feedback, and if it''s *appropriate* or necessary disable other actions but not if you can avoidit; offer a way of cancelling anything that will take any time (which is nearly anything), whether it''s an explicit "cancel" widget or just initiating a different action. I can totally see some widget, perhaps something appropriate for scripteka, that could be general enough to handle this reusably. [Travis, with my pedantic hat on: Your "ParallelRequestManager" is actually a *serial* request manager (the requests are handled in series, not in parallel); your SerialRequestManager is more of a *single* request manager... ;-)] -- T.J. Crowder tj / crowder software / com On Jul 2, 5:52 am, "Ryan Gahl" <ryan.g...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Well, it does sound quite sensible, if not a bit heavy for your specific > problem (which, by the way is not rooted in the transport layer, but in the > UX layer... the user experience). The crux of your problem is that the user > is clicking something again. Why? Because he is unaware that anything is > going on from the first click (i.e. your request is taking longer than the > user expects and you give no indication that something is happening). The > most common pattern, which for all intents and purposes works and is far > less complicated to implement than the "request queue", is to implement a > "Loading..." shim that renders everything underneath it unclickable, and > goes away when the call returns. > > Now... if you''re hellbent on implementing the "request queue"... let me know > and I''ll offer up some suggestions (we have done something similar for other > issues). BUT, the answer I gave above is IMHO a more accurate solution if > you objectively look at the real issue. > > > > On Tue, Jul 1, 2008 at 7:18 PM, Travis Miller <greenie2...-/E1597aS9LQAvxtiuMwx3w@public.gmane.org> wrote: > > > I''m looking for a good pattern that prevents AJAX requests from > > overlapping. > > > Consider this scenario, using an address book application as an example: > > > 1. On the left side of the page, there''s a list of contacts. On the right > > side, there''s a box that shows the currently selected contact. (Only one > > contact can be open at a time.) > > 2. The user clicks on a contact to open it. > > 3. The app initiates an AJAX request, but it takes a while. Maybe the > > server has to do some extra processing for some reason. > > 4. The user gets impatient, and clicks on another contact before the first > > one has loaded, which initiates a second, parallel AJAX request. > > 5. The second contact loads immediately, and the user starts working with > > it, but then... > > 6. ...the first AJAX request finally completes, and the first contact gets > > loaded over the second! > > > Obviously, the first AJAX request should be canceled if a second request of > > the same type is issued while it''s still running. > > > Here''s what I''m thinking: a generalized utility class - say, > > SerialRequestManager - designed to handle all situations of this type. Sort > > of a wrapper around Ajax.Request. A setRequest() method would accept an > > Ajax.Request object (and, if one is already set, destroys the existing one > > first); you''d probably want a cancelRequest() method, as well. The same > > class could hide and show an activity indicator. > > > To stray from the original problem a bit: a variant class - > > ParallelRequestManager - could add incoming requests to a queue, rather than > > destroying existing ones; it would show the activity indicator when the > > first request was added to the queue, and hide it when the last remaining > > request in the queue completes. > > > Does any of this sound sensible? :) > > -- > Ryan Gahl > Manager, Senior Software Engineer > Nth Penguin, LLChttp://www.nthpenguin.com > -- > WebWidgetry.com / MashupStudio.com > Future Home of the World''s First Complete Web Platform > -- > Inquire: 1-920-574-2218 > Blog:http://www.someElement.com > LinkedIn Profile:http://www.linkedin.com/in/ryangahl--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
> But unless it''s unavoidable/inappropriate...Huh?! Probably "unavoidable/appropriate", eh? -- T.J. :-) On Jul 2, 11:37 am, "T.J. Crowder" <t...-MUGVhKWuB3Yd9SLi6J12IkEOCMrvLtNR@public.gmane.org> wrote:> Yes, very important to show immediate feedback so the user knows > what''s going on; shocking how often that isn''t done. In many cases, > just that alone is going to prevent the OP''s scenario with the > impatient user. > > But unless it''s unavoidable/inappropriate, I''m not a fan of that > preventing other actions. The number of times I''ve clicked the wrong > thing and been frustrated because I couldn''t do what I wanted to do > until the thing I didn''t want to do finishes... > > So my take is: Offer immediate feedback, and if it''s *appropriate* or > necessary disable other actions but not if you can avoidit; offer a > way of cancelling anything that will take any time (which is nearly > anything), whether it''s an explicit "cancel" widget or just initiating > a different action. > > I can totally see some widget, perhaps something appropriate for > scripteka, that could be general enough to handle this reusably. > > [Travis, with my pedantic hat on: Your "ParallelRequestManager" is > actually a *serial* request manager (the requests are handled in > series, not in parallel); your SerialRequestManager is more of a > *single* request manager... ;-)] > -- > T.J. Crowder > tj / crowder software / com > > On Jul 2, 5:52 am, "Ryan Gahl" <ryan.g...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Well, it does sound quite sensible, if not a bit heavy for your specific > > problem (which, by the way is not rooted in the transport layer, but in the > > UX layer... the user experience). The crux of your problem is that the user > > is clicking something again. Why? Because he is unaware that anything is > > going on from the first click (i.e. your request is taking longer than the > > user expects and you give no indication that something is happening). The > > most common pattern, which for all intents and purposes works and is far > > less complicated to implement than the "request queue", is to implement a > > "Loading..." shim that renders everything underneath it unclickable, and > > goes away when the call returns. > > > Now... if you''re hellbent on implementing the "request queue"... let me know > > and I''ll offer up some suggestions (we have done something similar for other > > issues). BUT, the answer I gave above is IMHO a more accurate solution if > > you objectively look at the real issue. > > > On Tue, Jul 1, 2008 at 7:18 PM, Travis Miller <greenie2...-/E1597aS9LQAvxtiuMwx3w@public.gmane.org> wrote: > > > > I''m looking for a good pattern that prevents AJAX requests from > > > overlapping. > > > > Consider this scenario, using an address book application as an example: > > > > 1. On the left side of the page, there''s a list of contacts. On the right > > > side, there''s a box that shows the currently selected contact. (Only one > > > contact can be open at a time.) > > > 2. The user clicks on a contact to open it. > > > 3. The app initiates an AJAX request, but it takes a while. Maybe the > > > server has to do some extra processing for some reason. > > > 4. The user gets impatient, and clicks on another contact before the first > > > one has loaded, which initiates a second, parallel AJAX request. > > > 5. The second contact loads immediately, and the user starts working with > > > it, but then... > > > 6. ...the first AJAX request finally completes, and the first contact gets > > > loaded over the second! > > > > Obviously, the first AJAX request should be canceled if a second request of > > > the same type is issued while it''s still running. > > > > Here''s what I''m thinking: a generalized utility class - say, > > > SerialRequestManager - designed to handle all situations of this type. Sort > > > of a wrapper around Ajax.Request. A setRequest() method would accept an > > > Ajax.Request object (and, if one is already set, destroys the existing one > > > first); you''d probably want a cancelRequest() method, as well. The same > > > class could hide and show an activity indicator. > > > > To stray from the original problem a bit: a variant class - > > > ParallelRequestManager - could add incoming requests to a queue, rather than > > > destroying existing ones; it would show the activity indicator when the > > > first request was added to the queue, and hide it when the last remaining > > > request in the queue completes. > > > > Does any of this sound sensible? :) > > > -- > > Ryan Gahl > > Manager, Senior Software Engineer > > Nth Penguin, LLChttp://www.nthpenguin.com > > -- > > WebWidgetry.com / MashupStudio.com > > Future Home of the World''s First Complete Web Platform > > -- > > Inquire: 1-920-574-2218 > > Blog:http://www.someElement.com > > LinkedIn Profile:http://www.linkedin.com/in/ryangahl > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---