Quick Ajax Question

James Smith wrote:

This is my current sequence of actions:

- I have a link_to in a rhtml file that when clicked on calls a method
in my controller

- This method runs through a loop

- At some points in this loop i would like to be able to stop and update
something in my rhtml file (and hence the webpage), and then continue
back on with the loop

- is this possible?

This is the fundamental problem with responsive GUIs - you can't just go into a loop from an event handler.

(Note that everything from the Model down thru the database is just one huge system to keep the GUI responsive without looping over updating data and such...)

If I had this problem with a desktop GUI (such as a Win32 window), I would start a window timer, and then "time slice" the loop. I would store its looping index in a window variable, and at each timer tick I would update the index, run one tick of the looped activity, and then optionally update the screen.

Desktops prefer that system (it's often a better design than threading), and they allow window timers with 0 duration, to execute each time the CPU is idle. The result is perfectly responsive, and you obviously can't do it.

The new pattern here is to use periodically_call_remote, and then do a small batch of items. Maybe loop until you find a reason to update the screen. Then return an update, store your looping index, and await the next event. But you can't set periodically_call_remote to less than a second, because it slowly beats the crap out of every layer in your system, from the browser to the server.

The next more sadistic technique would be to start a timer (or possibly even - shudder - a thread) in the server. It will loop thru items, and push window updates as objects into a database queue. Then you use periodically_call_remote, with an easier frequency, to pop that queue and update the browser. Note that storing the queue in the database takes care of all the ACID concurrency the queue needs, and starting a new thread might be safe. Only do that as a last resort - look for a timer system so Rails can send its unused CPU cycles to your background task.

James-

  You can't really do what you are thinking of with stock rails because it doesn no output buffering. the response will not get sent to the browser until it is entriely done rendering everything. You cannot call a render in a loop and have it update the page each time thru the loop. You probably want to look into comet style push server. There is a rails plugin called jugernaut that may help you. Or you may want to look into backgroundrb.

  WHat you want is very difficult to do over HTTP which is a stateless protocol. You are trying to apply desktop app semantics to web apps and it doesn't convert over very well.

Cheers-

-- Ezra Zygmuntowicz-- Lead Rails Evangelist
-- ez@engineyard.com
-- Engine Yard, Serious Rails Hosting
-- (866) 518-YARD (9273)

Ezra Zygmuntowicz wrote:

WHat you want is very difficult to do over HTTP which is a stateless
protocol. You are trying to apply desktop app semantics to web apps
and it doesn't convert over very well.

Which is why everyone does it using periodically_call_remote(), slogging the browser and the server. GMail allegedly does it by leaving the Ajax wire open and never (deliberately) closing it. One could do that with raw HTTP, but how do you get a handle to the server's socket from inside Rails??