Hello, Here''s a mind bender. Normally, we want all our Web 2.0 actions to happen asynchronously. This allows for multiple actions to occur and finish when they are ready. We can invoke the XMLHttpRequest "synchronously" but there are some dangers with that. If it takes a long time for the server to respond, the web browser will be completely frozen during that time, giving the appearance that it has crashed. With that background, here''s my issue... I have a form with several text fields. When an "onchange" occurs the data is saved to the database via AJAX. So you can imagine entering 20 items and after you tab off of each one that data gets immediately saved to the database without further action from the user. Let''s call this an "auto-save" and it works great. Now imagine that in addition to the text fields, there are a few buttons on the page. Preferably, I''d like the clicking of a button to "wait" while any pending XMLHTTPRequests are active. Please correct me here if I''m wrong but I believe my options are: 1) Make all auto-save calls "synchronous". 2) Leave auto-save calls in async mode and pray that they finish before the "onclick" of the button. You can also show a message "hey, an auto-save is busy" when you click but that is annoying. The user shouldn''t be blocked out and require a second click because the auto- save needed 100 milliseconds to complete. 3) Do some polling in the "onclick" of the button and don''t allow the button action to continue until all XMLHTTPRequests are complete. Right now I''m doing #2 above. Most of the time, users are tabbing and the auto-save happens quickly so they never notice any quirkiness. However, when they do decide to type a value, not tab off, but immediately click the action button they get the warning message about the auto save in progress. All of the auto-save actions "push" a value into a global array when the request is sent then "pop" the value after the request returns. This is how I can determine if there are any outstanding AJAX requests by verifying that the array is empty. Option #3 seems ideal but I can''t get it to work. It appears that the javascript interpreter is single threaded. I just loop for eternity checking to see when that global array becomes empty but it never does. The interpreter doesn''t divide up its processing to allow the array to get "popped" in an alternate thread. Right now I''m thinking of going for option #1, but as stated above, it has it''s own set of issues. Does anyone have some pearls of wisdom to share? Inquiring minds want to know. Thanks in advance, -- Aaron --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
:) You''re missing #4, the right answer... Disable the buttons (or set a "saveInProgress" flag) prior to firing autosave, and revert back to "enabled" state on success... easy shmeasy. On 10/4/07, arosenzweig <arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org> wrote:> > > Hello, > > Here''s a mind bender. Normally, we want all our Web 2.0 actions to > happen asynchronously. This allows for multiple actions to occur and > finish when they are ready. We can invoke the XMLHttpRequest > "synchronously" but there are some dangers with that. If it takes a > long time for the server to respond, the web browser will be > completely frozen during that time, giving the appearance that it has > crashed. With that background, here''s my issue... > > I have a form with several text fields. When an "onchange" occurs the > data is saved to the database via AJAX. So you can imagine entering 20 > items and after you tab off of each one that data gets immediately > saved to the database without further action from the user. Let''s call > this an "auto-save" and it works great. > > Now imagine that in addition to the text fields, there are a few > buttons on the page. Preferably, I''d like the clicking of a button to > "wait" while any pending XMLHTTPRequests are active. Please correct me > here if I''m wrong but I believe my options are: > > 1) Make all auto-save calls "synchronous". > > 2) Leave auto-save calls in async mode and pray that they finish > before the "onclick" of the button. You can also show a message "hey, > an auto-save is busy" when you click but that is annoying. The user > shouldn''t be blocked out and require a second click because the auto- > save needed 100 milliseconds to complete. > > 3) Do some polling in the "onclick" of the button and don''t allow the > button action to continue until all XMLHTTPRequests are complete. > > Right now I''m doing #2 above. Most of the time, users are tabbing and > the auto-save happens quickly so they never notice any quirkiness. > However, when they do decide to type a value, not tab off, but > immediately click the action button they get the warning message about > the auto save in progress. All of the auto-save actions "push" a value > into a global array when the request is sent then "pop" the value > after the request returns. This is how I can determine if there are > any outstanding AJAX requests by verifying that the array is empty. > > Option #3 seems ideal but I can''t get it to work. It appears that the > javascript interpreter is single threaded. I just loop for eternity > checking to see when that global array becomes empty but it never > does. The interpreter doesn''t divide up its processing to allow the > array to get "popped" in an alternate thread. > > Right now I''m thinking of going for option #1, but as stated above, it > has it''s own set of issues. > > Does anyone have some pearls of wisdom to share? Inquiring minds want > to know. > > Thanks in advance, > -- Aaron > > > > >-- Ryan Gahl Manager, Senior Software Engineer Nth Penguin, LLC http://www.nthpenguin.com -- Architect WebWidgetry.com / MashupStudio.com Future Home of the World''s First Complete Web Platform -- Inquire: 1-262-951-6727 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 -~----------~----~----~----~------~----~------~--~---
if you go the "setting the flag" route, you would just add logic in your button handlers that say "if not save in progress already, save, otherwise don''t save" personally I''d go with disabling the interaction temporarily (with the button, not the entire browser) On 10/4/07, Ryan Gahl <ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > :) You''re missing #4, the right answer... > > Disable the buttons (or set a "saveInProgress" flag) prior to firing > autosave, and revert back to "enabled" state on success... easy shmeasy. > > On 10/4/07, arosenzweig <arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org> wrote: > > > > > > Hello, > > > > Here''s a mind bender. Normally, we want all our Web 2.0 actions to > > happen asynchronously. This allows for multiple actions to occur and > > finish when they are ready. We can invoke the XMLHttpRequest > > "synchronously" but there are some dangers with that. If it takes a > > long time for the server to respond, the web browser will be > > completely frozen during that time, giving the appearance that it has > > crashed. With that background, here''s my issue... > > > > I have a form with several text fields. When an "onchange" occurs the > > data is saved to the database via AJAX. So you can imagine entering 20 > > items and after you tab off of each one that data gets immediately > > saved to the database without further action from the user. Let''s call > > this an "auto-save" and it works great. > > > > Now imagine that in addition to the text fields, there are a few > > buttons on the page. Preferably, I''d like the clicking of a button to > > "wait" while any pending XMLHTTPRequests are active. Please correct me > > here if I''m wrong but I believe my options are: > > > > 1) Make all auto-save calls "synchronous". > > > > 2) Leave auto-save calls in async mode and pray that they finish > > before the "onclick" of the button. You can also show a message "hey, > > an auto-save is busy" when you click but that is annoying. The user > > shouldn''t be blocked out and require a second click because the auto- > > save needed 100 milliseconds to complete. > > > > 3) Do some polling in the "onclick" of the button and don''t allow the > > button action to continue until all XMLHTTPRequests are complete. > > > > Right now I''m doing #2 above. Most of the time, users are tabbing and > > the auto-save happens quickly so they never notice any quirkiness. > > However, when they do decide to type a value, not tab off, but > > immediately click the action button they get the warning message about > > the auto save in progress. All of the auto-save actions "push" a value > > into a global array when the request is sent then "pop" the value > > after the request returns. This is how I can determine if there are > > any outstanding AJAX requests by verifying that the array is empty. > > > > Option #3 seems ideal but I can''t get it to work. It appears that the > > javascript interpreter is single threaded. I just loop for eternity > > checking to see when that global array becomes empty but it never > > does. The interpreter doesn''t divide up its processing to allow the > > array to get "popped" in an alternate thread. > > > > Right now I''m thinking of going for option #1, but as stated above, it > > has it''s own set of issues. > > > > Does anyone have some pearls of wisdom to share? Inquiring minds want > > to know. > > > > Thanks in advance, > > -- Aaron > > > > > > > > > > > > > -- > Ryan Gahl > Manager, Senior Software Engineer > Nth Penguin, LLC > http://www.nthpenguin.com > -- > Architect > WebWidgetry.com / MashupStudio.com > Future Home of the World''s First Complete Web Platform > -- > Inquire: 1-262-951-6727 > Blog: http://www.someElement.com > LinkedIn Profile: http://www.linkedin.com/in/ryangahl-- Ryan Gahl Manager, Senior Software Engineer Nth Penguin, LLC http://www.nthpenguin.com -- Architect WebWidgetry.com / MashupStudio.com Future Home of the World''s First Complete Web Platform -- Inquire: 1-262-951-6727 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 -~----------~----~----~----~------~----~------~--~---
arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org
2007-Oct-04 22:23 UTC
Re: AJAX vs. SJAX and single threaded javascript
Ryan thanks for your fast reply but I think the root problem still remains. The desired effect is: "The user types in some text then immediately clicks the button, after a brief pause for the auto-save to complete the button action should go." I believe the solution you offered would allow us to either "allow or deny" the button press, but it won''t allow a delay while ajax calls are ongoing and then allow the button press. In other words its not: "Click, get message that you have to wait or have a grayed out button, then click again" But rather: "Click... brief pause, button action invokes." Perhaps SJAX is the only way to do this due to the single threaded nature of the javascript interpreter. If it wasn''t single threaded I could possibly sleep or keep looping and waiting for all AJAX requests to come back before executing the button click logic. -- Aaron "Ryan Gahl" <ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> Sent by: rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org 04-10-2007 04:41 PM Please respond to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org cc Subject [Rails-spinoffs] Re: AJAX vs. SJAX and single threaded javascript if you go the "setting the flag" route, you would just add logic in your button handlers that say "if not save in progress already, save, otherwise don''t save" personally I''d go with disabling the interaction temporarily (with the button, not the entire browser) On 10/4/07, Ryan Gahl <ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: :) You''re missing #4, the right answer... Disable the buttons (or set a "saveInProgress" flag) prior to firing autosave, and revert back to "enabled" state on success... easy shmeasy. On 10/4/07, arosenzweig <arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org > wrote: Hello, Here''s a mind bender. Normally, we want all our Web 2.0 actions to happen asynchronously. This allows for multiple actions to occur and finish when they are ready. We can invoke the XMLHttpRequest "synchronously" but there are some dangers with that. If it takes a long time for the server to respond, the web browser will be completely frozen during that time, giving the appearance that it has crashed. With that background, here''s my issue... I have a form with several text fields. When an "onchange" occurs the data is saved to the database via AJAX. So you can imagine entering 20 items and after you tab off of each one that data gets immediately saved to the database without further action from the user. Let''s call this an "auto-save" and it works great. Now imagine that in addition to the text fields, there are a few buttons on the page. Preferably, I''d like the clicking of a button to "wait" while any pending XMLHTTPRequests are active. Please correct me here if I''m wrong but I believe my options are: 1) Make all auto-save calls "synchronous". 2) Leave auto-save calls in async mode and pray that they finish before the "onclick" of the button. You can also show a message "hey, an auto-save is busy" when you click but that is annoying. The user shouldn''t be blocked out and require a second click because the auto- save needed 100 milliseconds to complete. 3) Do some polling in the "onclick" of the button and don''t allow the button action to continue until all XMLHTTPRequests are complete. Right now I''m doing #2 above. Most of the time, users are tabbing and the auto-save happens quickly so they never notice any quirkiness. However, when they do decide to type a value, not tab off, but immediately click the action button they get the warning message about the auto save in progress. All of the auto-save actions "push" a value into a global array when the request is sent then "pop" the value after the request returns. This is how I can determine if there are any outstanding AJAX requests by verifying that the array is empty. Option #3 seems ideal but I can''t get it to work. It appears that the javascript interpreter is single threaded. I just loop for eternity checking to see when that global array becomes empty but it never does. The interpreter doesn''t divide up its processing to allow the array to get "popped" in an alternate thread. Right now I''m thinking of going for option #1, but as stated above, it has it''s own set of issues. Does anyone have some pearls of wisdom to share? Inquiring minds want to know. Thanks in advance, -- Aaron http://www.nthpenguin.com -- Architect WebWidgetry.com / MashupStudio.com Future Home of the World''s First Complete Web Platform -- Inquire: 1-262-951-6727 Blog: http://www.someElement.com LinkedIn Profile: http://www.linkedin.com/in/ryangahl -- Ryan Gahl Manager, Senior Software Engineer Nth Penguin, LLC http://www.nthpenguin.com -- Architect WebWidgetry.com / MashupStudio.com Future Home of the World''s First Complete Web Platform -- Inquire: 1-262-951-6727 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 -~----------~----~----~----~------~----~------~--~---
On 10/5/07, arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org <arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org> wrote:> "The user types in some text then immediately clicks the button, after a brief pause for the auto-save to complete the button action should go." >function buttonhandler(){ if (autosave_in_progress){ setTimeout(buttonhandler, 100); } else { button_action(); } } and set this as the event handler for the button. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Indeed... OP dude - it''s all about the closures. This is the kind of thinking I was getting at... On 10/4/07, Martin Bialasinski <klingeling-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > > On 10/5/07, arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org <arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org> wrote: > > > "The user types in some text then immediately clicks the button, after a > brief pause for the auto-save to complete the button action should go." > > > > function buttonhandler(){ > if (autosave_in_progress){ > setTimeout(buttonhandler, 100); > } else { > button_action(); > } > } > > and set this as the event handler for the button. > > > >-- Ryan Gahl Manager, Senior Software Engineer Nth Penguin, LLC http://www.nthpenguin.com -- Architect WebWidgetry.com / MashupStudio.com Future Home of the World''s First Complete Web Platform -- Inquire: 1-262-951-6727 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 -~----------~----~----~----~------~----~------~--~---
On 10/5/07, Ryan Gahl <ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Indeed... OP dude - it''s all about the closures.Except there are no closures involved :-) --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
On 04/10/2007, arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org <arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org> wrote:> > > Ryan thanks for your fast reply but I think the root problem still > remains. The desired effect is: > > "The user types in some text then immediately clicks the button, after a > brief pause for the auto-save to complete the button action should go." > > I believe the solution you offered would allow us to either "allow or > deny" the button press, but it won''t allow a delay while ajax calls are > ongoing and then allow the button press. > > In other words its not: > > "Click, get message that you have to wait or have a grayed out button, > then click again" > > But rather: > > "Click... brief pause, button action invokes." > > Perhaps SJAX is the only way to do this due to the single threaded nature > of the javascript interpreter. If it wasn''t single threaded I could possibly > sleep or keep looping and waiting for all AJAX requests to come back before > executing the button click logic. > > -- Aaron > > > > *"Ryan Gahl" <ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>* > Sent by: rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org > > 04-10-2007 04:41 PM Please respond to > rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org > > To > rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org cc > > Subject > [Rails-spinoffs] Re: AJAX vs. SJAX and single threaded javascript > > > > > > > if you go the "setting the flag" route, you would just add logic in your > button handlers that say "if not save in progress already, save, otherwise > don''t save" > > personally I''d go with disabling the interaction temporarily (with the > button, not the entire browser) > > On 10/4/07, *Ryan Gahl* <*ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org* <ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>> > wrote: > :) You''re missing #4, the right answer... > > Disable the buttons (or set a "saveInProgress" flag) prior to firing > autosave, and revert back to "enabled" state on success... easy shmeasy. > > > On 10/4/07, *arosenzweig* <*arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org *<arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org>> > wrote: > > Hello, > > Here''s a mind bender. Normally, we want all our Web 2.0 actions to > happen asynchronously. This allows for multiple actions to occur and > finish when they are ready. We can invoke the XMLHttpRequest > "synchronously" but there are some dangers with that. If it takes a > long time for the server to respond, the web browser will be > completely frozen during that time, giving the appearance that it has > crashed. With that background, here''s my issue... > > I have a form with several text fields. When an "onchange" occurs the > data is saved to the database via AJAX. So you can imagine entering 20 > items and after you tab off of each one that data gets immediately > saved to the database without further action from the user. Let''s call > this an "auto-save" and it works great. > > Now imagine that in addition to the text fields, there are a few > buttons on the page. Preferably, I''d like the clicking of a button to > "wait" while any pending XMLHTTPRequests are active. Please correct me > here if I''m wrong but I believe my options are: > > 1) Make all auto-save calls "synchronous". > > 2) Leave auto-save calls in async mode and pray that they finish > before the "onclick" of the button. You can also show a message "hey, > an auto-save is busy" when you click but that is annoying. The user > shouldn''t be blocked out and require a second click because the auto- > save needed 100 milliseconds to complete. > > 3) Do some polling in the "onclick" of the button and don''t allow the > button action to continue until all XMLHTTPRequests are complete. > > Right now I''m doing #2 above. Most of the time, users are tabbing and > the auto-save happens quickly so they never notice any quirkiness. > However, when they do decide to type a value, not tab off, but > immediately click the action button they get the warning message about > the auto save in progress. All of the auto-save actions "push" a value > into a global array when the request is sent then "pop" the value > after the request returns. This is how I can determine if there are > any outstanding AJAX requests by verifying that the array is empty. > > Option #3 seems ideal but I can''t get it to work. It appears that the > javascript interpreter is single threaded. I just loop for eternity > checking to see when that global array becomes empty but it never > does. The interpreter doesn''t divide up its processing to allow the > array to get "popped" in an alternate thread. > > Right now I''m thinking of going for option #1, but as stated above, it > has it''s own set of issues. > > Does anyone have some pearls of wisdom to share? Inquiring minds want > to know. > > Thanks in advance, > -- Aaron > > > http://www.nthpenguin.com > -- > Architect > WebWidgetry.com / MashupStudio.com > Future Home of the World''s First Complete Web Platform > -- > Inquire: 1-262-951-6727 > Blog: *http://www.someElement.com* <http://www.someelement.com/> > LinkedIn Profile: *http://www.linkedin.com/in/ryangahl*<http://www.linkedin.com/in/ryangahl> > > > > -- > Ryan Gahl > Manager, Senior Software Engineer > Nth Penguin, LLC* > **http://www.nthpenguin.com* <http://www.nthpenguin.com/> > -- > Architect > WebWidgetry.com / MashupStudio.com > Future Home of the World''s First Complete Web Platform > -- > Inquire: 1-262-951-6727 > Blog: *http://www.someElement.com* <http://www.someelement.com/> > LinkedIn Profile: *http://www.linkedin.com/in/ryangahl*<http://www.linkedin.com/in/ryangahl> > > > >Maybe something like this ... function buttonhandler(){ if (0 != Ajax.activeRequestCount){ setTimeout(buttonhandler, 100); } else { button_action(); } } The activeRequestCount property is auto-maintained by using an onCreate/onComplete Responder (In V1.6.0_RC0 look at lines 1182 - 1189). You may need to also add your own onException handler to deal with things going wrong within an Ajax callback and maybe resulting in the activeRequestCount NOT being zero due to an exception - not sure how to generate an exception to test this. -- ----- Richard Quadling Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731 "Standing on the shoulders of some very clever giants!" --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
When you call setTimout the buttonhandler reference becomes a closure :) On 10/4/07, Martin Bialasinski <klingeling-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > > On 10/5/07, Ryan Gahl <ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > Indeed... OP dude - it''s all about the closures. > > Except there are no closures involved :-) > > > >-- Ryan Gahl Manager, Senior Software Engineer Nth Penguin, LLC http://www.nthpenguin.com -- Architect WebWidgetry.com / MashupStudio.com Future Home of the World''s First Complete Web Platform -- Inquire: 1-262-951-6727 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 -~----------~----~----~----~------~----~------~--~---
On 10/5/07, Ryan Gahl <ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> When you call setTimout the buttonhandler reference becomes a closure :)I don''t quite understand what you mean. A variable is not a closure. When the function gets executed by the timeout, it does not share neither scope nor execution context with the first invocation. There is no forming of a closure anywhere. --~--~---------~--~----~------------~-------~--~----~ 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 it does... autosave_in_progress is closed within the function reference you pass in. Just because you don''t have to use an anonymous function does not mean it''s not a closure. setTimeout is based on closures -- you pass in a function reference and it can be executed any time in the future (even well after the initial scope where you defined buttonhandler or the variable autosave_in_progress is long gone therefore making that uncallable elsewhere). It would not work if it wasn''t using a closure. function foo() { var autosave_in_progress; function buttonhandler(){ if (autosave_in_progress){ setTimeout(buttonhandler, 100); } else { button_action(); } } }(); Can you see how it''s a closure now? In the above, foo is executed, and the buttonhandler function is defined within it, but is executed only _after_ that scope is gone. Both the variable autosave_in_progress and the function buttonhandler as closed over. On 10/5/07, Martin Bialasinski <klingeling-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > > On 10/5/07, Ryan Gahl <ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > When you call setTimout the buttonhandler reference becomes a closure :) > > I don''t quite understand what you mean. A variable is not a closure. > When the function gets executed by the timeout, it does not share > neither scope nor execution context with the first invocation. There > is no forming of a closure anywhere. > > > >-- Ryan Gahl Manager, Senior Software Engineer Nth Penguin, LLC http://www.nthpenguin.com -- Architect WebWidgetry.com / MashupStudio.com Future Home of the World''s First Complete Web Platform -- Inquire: 1-262-951-6727 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 -~----------~----~----~----~------~----~------~--~---
arosenzweig-fbjq1H7RxnhWk0Htik3J/w@public.gmane.org
2007-Oct-05 19:42 UTC
Re: AJAX vs. SJAX and single threaded javascript
Thank you very much - Ryan Gahl, Martin Bialasinski, and Richard Quadling. That''s a neat design pattern you got there. I like it a lot! I wanted to take a moment to tell you what I discovered today. I found that for our app SJAX (Synchronous AJAX) calls were very quick and actually afforded a better user experience. It''s easier to chain the order of updates on the screen and the "pausing" effect I was looking for just happened without additional work. We may change our mind later and come up with something else related to your design pattern but for right now, it''s good. If there is something that would cause the reply to take a long time, there is probably something wrong with the server. For hard core data entry (which is what our app is about), it''s not good to have you think that a lot of asynchronous saves got saved when they didn''t... it''s better to see the spinning pinwheel as soon as there is a problem with the server. I tweaked your design pattern slightly and experimented with it: function buttonhandler(){ if (autosave_in_progress()){ setTimeout(buttonhandler, 100); } else { button_action(); } return false; //This is the small one line tweak } The "autosave_in_progress" is a function that could be defined in any particular way to return a "true" or a "false". It might just look at "0 != Ajax.activeRequestCount" but it could do something else. This is neat in that it gives that kind of "polling" idea which allows for ajax calls to do their thing and for you to keep checking for their completion before you perform another action. You still have to be careful you hit all the possiblities like Hrefs, Submit buttons, etc. You also have to be careful that action doesn''t actually continue down it''s path that''s why I put in a "return false" there at the end. Think of an href.onclick where you don''t want the clicking of the link to immediately invoke, but only after "auto_save_in_progress()" evaluates to "true". In the case of a "onbeforeunload" (when you are leaving or refreshing the page) you might have to use SJAX, it''s probably the only way. Without SJAX for the onbeforeunload, you''d have to make an immediate decision if you want stop the user or let them move on. Cheers, --Aaron "Ryan Gahl" <ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> Sent by: rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org 05-10-2007 01:00 PM Please respond to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org cc Subject [Rails-spinoffs] Re: AJAX vs. SJAX and single threaded javascript Yes it does... autosave_in_progress is closed within the function reference you pass in. Just because you don''t have to use an anonymous function does not mean it''s not a closure. setTimeout is based on closures -- you pass in a function reference and it can be executed any time in the future (even well after the initial scope where you defined buttonhandler or the variable autosave_in_progress is long gone therefore making that uncallable elsewhere). It would not work if it wasn''t using a closure. function foo() { var autosave_in_progress; function buttonhandler(){ if (autosave_in_progress){ setTimeout(buttonhandler, 100); } else { button_action(); } } }(); Can you see how it''s a closure now? In the above, foo is executed, and the buttonhandler function is defined within it, but is executed only _after_ that scope is gone. Both the variable autosave_in_progress and the function buttonhandler as closed over. On 10/5/07, Martin Bialasinski <klingeling-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: On 10/5/07, Ryan Gahl <ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> When you call setTimout the buttonhandler reference becomes a closure :)I don''t quite understand what you mean. A variable is not a closure. When the function gets executed by the timeout, it does not share neither scope nor execution context with the first invocation. There is no forming of a closure anywhere. http://www.nthpenguin.com -- Architect WebWidgetry.com / MashupStudio.com Future Home of the World''s First Complete Web Platform -- Inquire: 1-262-951-6727 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 -~----------~----~----~----~------~----~------~--~---
We might be speaking about different things here. When calling setTimeout() with a function reference, the JS engine does not form a new closure as part of the setTimeout inner workings. If setTimeout would create a closure, this example sould log "1" and not "undefined": function foo(){ console.log(test); } function bar(){ var test = 1; setTimeout(foo, 100); } bar(); What you see in your example is that buttonhandler itself forms a closure as it accesses a variable in its outer scope. There is a closure because of the way the function is defined, not because setTimeout got a function reference. Please correct me anyone if my understanding of the situation is off. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
It''s still creating a closure, but now it''s not closing over the variable inside bar (obvisouly since you are not passing bar as the function reference). Any local vars that are available within or defined by foo will have been closed over though. function blah() { var hooblyHoo = 1; function foo() { alert(hooblyHoo); } setTimeout(foo, 100); }(); I made this one simpler... it''s a closure... no ifs ands or buts about it. So is the original one. When calling setTimeout() with a function reference, the JS engine> does not form a new closure as part of the setTimeout inner workings.Incorrect. On 10/5/07, Martin Bialasinski <klingeling-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > > We might be speaking about different things here. > > When calling setTimeout() with a function reference, the JS engine > does not form a new closure as part of the setTimeout inner workings. > > If setTimeout would create a closure, this example sould log "1" and > not "undefined": > > function foo(){ > console.log(test); > } > > function bar(){ > var test = 1; > setTimeout(foo, 100); > } > > bar(); > > What you see in your example is that buttonhandler itself forms a > closure as it accesses a variable in its outer scope. There is a > closure because of the way the function is defined, not because > setTimeout got a function reference. > > Please correct me anyone if my understanding of the situation is off. > > > >-- Ryan Gahl Manager, Senior Software Engineer Nth Penguin, LLC http://www.nthpenguin.com -- Architect WebWidgetry.com / MashupStudio.com Future Home of the World''s First Complete Web Platform -- Inquire: 1-262-951-6727 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 -~----------~----~----~----~------~----~------~--~---
function blah() { var auto_save_in_progress = true; function buttonhandler() { if (auto_save_in_progress) setTimeout(buttonhandler, 100); } buttonhandler() }(); ''tis a closure just like the previous foo example, only difference is it''s harder to see because of its recursive nature. On 10/5/07, Ryan Gahl <ryan.gahl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > It''s still creating a closure, but now it''s not closing over the variable > inside bar (obvisouly since you are not passing bar as the function > reference). Any local vars that are available within or defined by foo will > have been closed over though. > > function blah() { > var hooblyHoo = 1; > > function foo() { > alert(hooblyHoo); > } > > setTimeout(foo, 100); > }(); > > I made this one simpler... it''s a closure... no ifs ands or buts about it. > So is the original one. > > When calling setTimeout() with a function reference, the JS engine > > does not form a new closure as part of the setTimeout inner workings. > > > Incorrect. > > > > > On 10/5/07, Martin Bialasinski <klingeling-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > > We might be speaking about different things here. > > > > When calling setTimeout() with a function reference, the JS engine > > does not form a new closure as part of the setTimeout inner workings. > > > > If setTimeout would create a closure, this example sould log "1" and > > not "undefined": > > > > function foo(){ > > console.log (test); > > } > > > > function bar(){ > > var test = 1; > > setTimeout(foo, 100); > > } > > > > bar(); > > > > What you see in your example is that buttonhandler itself forms a > > closure as it accesses a variable in its outer scope. There is a > > closure because of the way the function is defined, not because > > setTimeout got a function reference. > > > > Please correct me anyone if my understanding of the situation is off. > > > > > > > > > > > -- > Ryan Gahl > Manager, Senior Software Engineer > Nth Penguin, LLC > http://www.nthpenguin.com > -- > Architect > WebWidgetry.com / MashupStudio.com > Future Home of the World''s First Complete Web Platform > -- > Inquire: 1-262-951-6727 > Blog: http://www.someElement.com > LinkedIn Profile: http://www.linkedin.com/in/ryangahl >-- Ryan Gahl Manager, Senior Software Engineer Nth Penguin, LLC http://www.nthpenguin.com -- Architect WebWidgetry.com / MashupStudio.com Future Home of the World''s First Complete Web Platform -- Inquire: 1-262-951-6727 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 -~----------~----~----~----~------~----~------~--~---
you are not going to be able to use a global array to track requests, which is why you can''t get #3 to work. The array will stay the same as when you sent it.. but if you wrap your array in a class it will accept changes while requests are in progress, it will behave in the global sense that you want. This is how Prototype already provides a means to tell if there are outstanding requests. You can inspect the variable Ajax.activeRequestCount to see if requests are still active. You can also make your own that are arrays and are more customized, but if all you want to know is ''are there requests out'' then that answer is already available to your script you are just not using it because you are trying to use javascript global vars, which won''t work. Open up prototype and see how it''s handled.. activeRequestCount --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
I think you should accept the button click rather than fade the button, but then hold off on sending it until Ajax.activeRequestCount = 0.. this way you can process that last entry that the user made just before the button click.. and they won''t know anything but that a slight hang is happening on button click.. which is no surprise to most users.. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Except that some users will undoubtedly click multiple times because of the hang. Disabling interaction immediately following said interaction is a _very_ common UI development practice, for good reason. On 10/6/07, Lisa B <beforeamillionuniverses-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > > I think you should accept the button click rather than fade the > button, but then hold off on sending it until Ajax.activeRequestCount > = 0.. this way you can process that last entry that the user made > just before the button click.. and they won''t know anything but that a > slight hang is happening on button click.. which is no surprise to > most users.. > > > > >-- Ryan Gahl Manager, Senior Software Engineer Nth Penguin, LLC http://www.nthpenguin.com -- Architect WebWidgetry.com / MashupStudio.com Future Home of the World''s First Complete Web Platform -- Inquire: 1-262-951-6727 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 disabling the button on its own click is necessary any time you take over its default behavior and there could be a lag.. I was referring to disabling the button on each and every request triggered as other form fields are activated.. would be nicer to avoid that if possible.. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---