Cancel periodically_call_remote?


#1

So I have a periodically_call_remote call happenign every 5 seconds.
After about 10-20 seconds at most, everything that it needs to do is
done, and it doesn’t need to fire anymore.

Now, I can take advantage of the :condition argument to put in some
javascript variable such that it won’t actually make the call to the
server anymore. But the javascript timer is still firing–every five
seconds it’s deciding not to make the call to the server anymore.

If I leave the window open long enough, or have enough such windows
open, this starts causing noticeable slowdown in my browser. (Perhaps
some kidn of Firefox memory leak, perhaps not, who knows). I really want
the thing to just stop firing–not to fire every five seconds and check
to see if it should make the XML call to server, but just not fire at
all anymore, it’s done.

Is there any good way to do this?

Thanks for any advice.

Jonathan


#2

On Jul 25, 4:25 pm, Jonathan R. <rails-mailing-l…@andreas-
s.net> wrote:

I really want
the thing to just stop firing–not to fire every five seconds and check
to see if it should make the XML call to server, but just not fire at
all anymore, it’s done.

Is there any good way to do this?

You could try putting the periodically call remote inside a div, and
have the last periodic call clear the div.

~Rusty


#3

Hello,

Have you tried this:
http://tr.openmonkey.com/articles/2006/01/23/conditional-periodically_call_remote-in-rails

Dmitry

On Jul 25, 11:25 pm, Jonathan R. <rails-mailing-l…@andreas-


#4

Rusty B. wrote:

You could try putting the periodically call remote inside a div, and
have the last periodic call clear the div.

This is a FAQ, and that’s wrong because the setTimeout still exists,
and it will still reactivate that object in memory. The DIV only
creates it and pushes it into memory.

I say leave the dumb thing spinning on the user’s browser. They have
CPU cycles - you don’t!


Phlip
http://www.oreilly.com/catalog/9780596510657/
^ assert_xpath
http://tinyurl.com/23tlu5 <-- assert_raise_message


#5

Rusty B. wrote:

This might work for you. Create a variable and function, for example:
IWantToContinue = true;
function continueOrNot() {
if (IWantToContinue) return true;
this.stop();
return false;
}

That’s an interesting idea. Haven’t tried it yet, but it led me to
another idea, after looking at the source code generated by
periodically_call_remote, and tryign to understand what your this.stop()
did.

My new idea: stop using periodically_call_remote at all. Instead,
generate the Prototype javascript myself manually (based on the source
code I see periodically_call_remote generating), to do exactly the same
thing, but save the Prototype PeriodicalExecuter js object in a js
variable:

some_js_var = new PeriodicialExecuter(…

Now I can just call some_js_var.stop() at a future point. I think this
should work.

If the periodically_call_remote function were enhanced to take an
argument for a name of a js variable to use in this assignment (not sure
what you’d name this argument!), that would allow the
periodically_call_remote to be used itself, and take care of this FAQ!

Jonathan

Then set :condition=>“continueOrNot()”, and set IWantToContinue to
false with rjs when you are done.

To test it you can set :condition=>“continueOrNot() || alert(‘still
executing…’)”

~Rusty


#6

I took this idea and implemented it in my app.

In ApplicationHelper, I overrode the periodically_call_remote function
with:

def periodically_call_remote(options = {})
variable = options[:variable] ||= ‘poller’
frequency = options[:frequency] ||= 10
code = “#{variable} = new PeriodicalExecuter(function()
{#{remote_function(options)}}, #{frequency})”
javascript_tag(code)
end

This will store the PeriodicalExecuter in a variable. In order to set
the name of the variable, you can pass in a :variable option. By
default, it will use ‘poller’.

So you can do:

periodically_call_remote(:url => some_url, :update => ‘some_div’,
:variable => ‘my_var’)

And when you want to stop the polling, you can inject the following line
of javascript into your page:

Hope this helps anyone else who’s run into this.

Micah Winkelspecht

My new idea: stop using periodically_call_remote at all. Instead,
generate the Prototype javascript myself manually (based on the source
code I see periodically_call_remote generating), to do exactly the same
thing, but save the Prototype PeriodicalExecuter js object in a js
variable:

some_js_var = new PeriodicialExecuter(…

Now I can just call some_js_var.stop() at a future point. I think this
should work.

If the periodically_call_remote function were enhanced to take an
argument for a name of a js variable to use in this assignment (not sure
what you’d name this argument!), that would allow the
periodically_call_remote to be used itself, and take care of this FAQ!

Jonathan


#7

On Jul 25, 5:58 pm, Phlip removed_email_address@domain.invalid wrote:

Rusty B. wrote:

You could try putting the periodically call remote inside a div, and
have the last periodic call clear the div.

This is a FAQ, and that’s wrong because the setTimeout still exists,
and it will still reactivate that object in memory. The DIV only
creates it and pushes it into memory.

Emphasis on try.

This might work for you. Create a variable and function, for example:
IWantToContinue = true;
function continueOrNot() {
if (IWantToContinue) return true;
this.stop();
return false;
}

Then set :condition=>“continueOrNot()”, and set IWantToContinue to
false with rjs when you are done.

To test it you can set :condition=>“continueOrNot() || alert(‘still
executing…’)”

~Rusty


#8

This seems to be what I was loooking for.
Now what I would like to know is how can I restart the call?
Can I push it from the server based on new data now available?

What I am trying to accomplish is to only update a dom when data in the
database has changed.

Thanks

Micah Winkelspecht wrote:

I took this idea and implemented it in my app.

In ApplicationHelper, I overrode the periodically_call_remote function
with:

def periodically_call_remote(options = {})
variable = options[:variable] ||= ‘poller’
frequency = options[:frequency] ||= 10
code = “#{variable} = new PeriodicalExecuter(function()
{#{remote_function(options)}}, #{frequency})”
javascript_tag(code)
end

This will store the PeriodicalExecuter in a variable. In order to set
the name of the variable, you can pass in a :variable option. By
default, it will use ‘poller’.

So you can do:

periodically_call_remote(:url => some_url, :update => ‘some_div’,
:variable => ‘my_var’)

And when you want to stop the polling, you can inject the following line
of javascript into your page:


#9

Another thing you can do is to change the frequency to a very high
number after your desired condition is met. Technically, this doesn’t
cancel it, but it works.

On Aug 27 2008, 2:43 am, Micah Winkelspecht <rails-mailing-


#10

Micah Winkelspecht wrote:

def periodically_call_remote(options = {})
variable = options[:variable] ||= ‘poller’
frequency = options[:frequency] ||= 10
code = “#{variable} = new PeriodicalExecuter(function()
{#{remote_function(options)}}, #{frequency})”
javascript_tag(code)
end

Thanks alot! Helped me fix the problem as well.


#11

Jason Dely wrote:

This seems to be what I was loooking for.
Now what I would like to know is how can I restart the call?
Can I push it from the server based on new data now available?

I ran into these issue myself. After much struggle and frustration, it
dawned on me that doing periodic updates with straight up JavaScript is
really pretty easy. And, I found it to be more flexible anyway.

Here is an example of my solution. This happens to be jQuery, but the
same applies to Prototype:

var myInterval;

// Wait for DOM to load
$(document).ready(function() {
startUpdater();

// Setup start/stop buttons
$("#stop_refresh").click(stopUpdater);
$("#start_refresh").click(startUpdater);
});

function startUpdater() {
myInterval = window.setInterval(doUpdate, 2000);
}

function stopUpdater() {
window.clearInterval(myInterval);
return false;
}

function doUpdate() {
var url = “url/to/new/content”;
$("#content_div").load(url);
}

Note: this is also an Unobtrusive JavaScript solution, which is another
bonus.