// usage: var _pollInt = 0; function repetiousPollFn() { console.log(_pollInt++);
}
repetiousPollFn.repeat(.5);
Will, of course, repeat repetiousPollFn() every half second.
Almost identical to .delay(), except that it returns setInterval instead of setTimeout. One thing I intend to add is support for clearInterval, however I figured I'd at least bring it up here first. I've never proposed/contributed here before (i'm a lurker of the list :D ) - any guidance is appreciated.
Only suggestion i can think of is that your method strongly implies a
requirement that "repetitionsPollFn.repeat()" get assigned to a
variable so it can be cleared later:
var interval = repetitiousPollFn.repeat(0.5);
// interval is the setInterval ID
then later
window.clearInterval(interval);
i could also see potential for more "scheduling" options
(repeatUntilTime, repeatXTimes, etc) built into your #repeat idea, but
don't really have the time to flesh them out.
i find it an interesting idea though. :)
-joe t.
On Jun 23, 11:25 am, Rick Waldron <waldron.r...@gmail.com> wrote:
> // usage:
> var _pollInt = 0;
> function repetiousPollFn() {
> console.log(_pollInt++);
> }
> repetiousPollFn.repeat(.5);
> Will, of course, repeat repetiousPollFn() every half second.
> Almost identical to .delay(), except that it returns setInterval instead of
> setTimeout. One thing I intend to add is support for clearInterval, however
> I figured I'd at least bring it up here first. I've never
> proposed/contributed here before (i'm a lurker of the list :D ) - any
> guidance is appreciated.
> Only suggestion i can think of is that your method strongly implies a
> requirement that "repetitionsPollFn.repeat()" get assigned to a
> variable so it can be cleared later:
> var interval = repetitiousPollFn.repeat(0.5);
> // interval is the setInterval ID
> then later
> window.clearInterval(interval);
> i could also see potential for more "scheduling" options
> (repeatUntilTime, repeatXTimes, etc) built into your #repeat idea, but
> don't really have the time to flesh them out.
> i find it an interesting idea though. :)
> -joe t.
> On Jun 23, 11:25 am, Rick Waldron <waldron.r...@gmail.com> wrote:
> > I detest the way setInterval() looks, so I came up with this... have been
> > using it my personal JS for some time.
> > // usage:
> > var _pollInt = 0;
> > function repetiousPollFn() {
> > console.log(_pollInt++);
> > }
> > repetiousPollFn.repeat(.5);
> > Will, of course, repeat repetiousPollFn() every half second.
> > Almost identical to .delay(), except that it returns setInterval instead of
> > setTimeout. One thing I intend to add is support for clearInterval, however
> > I figured I'd at least bring it up here first. I've never
> > proposed/contributed here before (i'm a lurker of the list :D ) - any
> > guidance is appreciated.
I can't say I'm a big fan of this. For several reasons.
First, it's just a cosmetic replacement for setInterval(myfunction
(...).bind(), ...) which simply isn't all that bad.
Second, I'm not a fan of setInterval in general. I've seen some
rather nasty behavior with calls queuing up if the invoked function
takes longer than the delay to execute. In particular, this seems to
be an issue if you do something like put a laptop to sleep. (But
maybe others haven't seen this problem???) Thus, I prefer to use a
self-invoking timeout like so:
function myFunction() {
// do stuff ...
// call ourselves again
if (/*we want to continue?*/) setTimeout(myFunction, 1000)
}
This doesn't call the function at exactly one second intervals, but
that type of accuracy is rarely important. Instead, it guarantees you
have at least one second of delay between invocations, which for
distributing cpu load or polling (the more common cases where
setInterval might be used), is more desireable.
Finally, as Joe T. points out, there should be a way of cancelling the
interval that doesn't require the user to store the returned value
(*that* is what I find most annoying, not the syntax of
"setInterval").
Thus, I'd suggest this instead:
Object.extend(Function.prototype, {
repeat: function(delay) {
// Reset state
if (this._repeater) delete this._repeater;
this._repeatTimeout = clearTimeout(this._repeatTimeout);
if (!delay) return; // (stop repeating if no args or delay==0)
// Create setTimeout-based invoker
var _method = this;
if (!this._repeater) this._repeater = function() {
// Let _method cancel repeat by doing "return false;"
if (_method() !== false) setTimeout(_method._repeater, delay);
}
var count = 0;
function foo() {
console.log(count++);
return count < 10; // Return "false" when count >= 10 to cancel
the repeat
}
// Start repeating 1/sec
foo.repeat(1000);
//... some time later change interval to 2/sec
foo.repeat(500);
// ... later still stop repeating.
foo.stopRepeating();
As you can see, this implementation of repeat() does a lot more for
you than simply alias'ing "setInterval":
- It guarantees your function is only invoked by one interval
- It makes changing the interval or cancelling it altogether
trivial.
- It allows you to conditionally cancel the repeat from w/in the
function itself.
The only thing missing is the bind() behavior but, well, that's what
bind is for. If you need to bind arguments, just bind() your
arguments first.
On Jun 23, 8:25 am, Rick Waldron <waldron.r...@gmail.com> wrote:
> // usage:
> var _pollInt = 0;
> function repetiousPollFn() {
> console.log(_pollInt++);
> }
> repetiousPollFn.repeat(.5);
> Will, of course, repeat repetiousPollFn() every half second.
> Almost identical to .delay(), except that it returns setInterval instead of
> setTimeout. One thing I intend to add is support for clearInterval, however
> I figured I'd at least bring it up here first. I've never
> proposed/contributed here before (i'm a lurker of the list :D ) - any
> guidance is appreciated.
On Wed, Jun 24, 2009 at 9:55 AM, Robert Kieffer <bro...@gmail.com> wrote:
> I can't say I'm a big fan of this. For several reasons.
> First, it's just a cosmetic replacement for setInterval(myfunction
> (...).bind(), ...) which simply isn't all that bad.
> Second, I'm not a fan of setInterval in general. I've seen some
> rather nasty behavior with calls queuing up if the invoked function
> takes longer than the delay to execute. In particular, this seems to
> be an issue if you do something like put a laptop to sleep. (But
> maybe others haven't seen this problem???) Thus, I prefer to use a
> self-invoking timeout like so:
> function myFunction() {
> // do stuff ...
> // call ourselves again
> if (/*we want to continue?*/) setTimeout(myFunction, 1000)
> }
> This doesn't call the function at exactly one second intervals, but
> that type of accuracy is rarely important. Instead, it guarantees you
> have at least one second of delay between invocations, which for
> distributing cpu load or polling (the more common cases where
> setInterval might be used), is more desireable.
> Finally, as Joe T. points out, there should be a way of cancelling the
> interval that doesn't require the user to store the returned value
> (*that* is what I find most annoying, not the syntax of
> "setInterval").
> Thus, I'd suggest this instead:
> Object.extend(Function.prototype, {
> repeat: function(delay) {
> // Reset state
> if (this._repeater) delete this._repeater;
> this._repeatTimeout = clearTimeout(this._repeatTimeout);
> if (!delay) return; // (stop repeating if no args or delay==0)
> // Create setTimeout-based invoker
> var _method = this;
> if (!this._repeater) this._repeater = function() {
> // Let _method cancel repeat by doing "return false;"
> if (_method() !== false) setTimeout(_method._repeater, delay);
> }
> var count = 0;
> function foo() {
> console.log(count++);
> return count < 10; // Return "false" when count >= 10 to cancel
> the repeat
> }
> // Start repeating 1/sec
> foo.repeat(1000);
> //... some time later change interval to 2/sec
> foo.repeat(500);
> // ... later still stop repeating.
> foo.stopRepeating();
> As you can see, this implementation of repeat() does a lot more for
> you than simply alias'ing "setInterval":
> - It guarantees your function is only invoked by one interval
> - It makes changing the interval or cancelling it altogether
> trivial.
> - It allows you to conditionally cancel the repeat from w/in the
> function itself.
> The only thing missing is the bind() behavior but, well, that's what
> bind is for. If you need to bind arguments, just bind() your
> arguments first.
> On Jun 23, 8:25 am, Rick Waldron <waldron.r...@gmail.com> wrote:
> > I detest the way setInterval() looks, so I came up with this... have been
> > using it my personal JS for some time.
> > // usage:
> > var _pollInt = 0;
> > function repetiousPollFn() {
> > console.log(_pollInt++);
> > }
> > repetiousPollFn.repeat(.5);
> > Will, of course, repeat repetiousPollFn() every half second.
> > Almost identical to .delay(), except that it returns setInterval instead
> of
> > setTimeout. One thing I intend to add is support for clearInterval,
> however
> > I figured I'd at least bring it up here first. I've never
> > proposed/contributed here before (i'm a lurker of the list :D ) - any
> > guidance is appreciated.
> On Wed, Jun 24, 2009 at 9:55 AM, Robert Kieffer <bro...@gmail.com> wrote:
>> I can't say I'm a big fan of this. For several reasons.
>> First, it's just a cosmetic replacement for setInterval(myfunction
>> (...).bind(), ...) which simply isn't all that bad.
>> Second, I'm not a fan of setInterval in general. I've seen some
>> rather nasty behavior with calls queuing up if the invoked function
>> takes longer than the delay to execute. In particular, this seems to
>> be an issue if you do something like put a laptop to sleep. (But
>> maybe others haven't seen this problem???) Thus, I prefer to use a
>> self-invoking timeout like so:
>> function myFunction() {
>> // do stuff ...
>> // call ourselves again
>> if (/*we want to continue?*/) setTimeout(myFunction, 1000)
>> }
>> This doesn't call the function at exactly one second intervals, but
>> that type of accuracy is rarely important. Instead, it guarantees you
>> have at least one second of delay between invocations, which for
>> distributing cpu load or polling (the more common cases where
>> setInterval might be used), is more desireable.
>> Finally, as Joe T. points out, there should be a way of cancelling the
>> interval that doesn't require the user to store the returned value
>> (*that* is what I find most annoying, not the syntax of
>> "setInterval").
>> Thus, I'd suggest this instead:
>> Object.extend(Function.prototype, {
>> repeat: function(delay) {
>> // Reset state
>> if (this._repeater) delete this._repeater;
>> this._repeatTimeout = clearTimeout(this._repeatTimeout);
>> if (!delay) return; // (stop repeating if no args or delay==0)
>> // Create setTimeout-based invoker
>> var _method = this;
>> if (!this._repeater) this._repeater = function() {
>> // Let _method cancel repeat by doing "return false;"
>> if (_method() !== false) setTimeout(_method._repeater, delay);
>> }
>> var count = 0;
>> function foo() {
>> console.log(count++);
>> return count < 10; // Return "false" when count >= 10 to cancel
>> the repeat
>> }
>> // Start repeating 1/sec
>> foo.repeat(1000);
>> //... some time later change interval to 2/sec
>> foo.repeat(500);
>> // ... later still stop repeating.
>> foo.stopRepeating();
>> As you can see, this implementation of repeat() does a lot more for
>> you than simply alias'ing "setInterval":
>> - It guarantees your function is only invoked by one interval
>> - It makes changing the interval or cancelling it altogether
>> trivial.
>> - It allows you to conditionally cancel the repeat from w/in the
>> function itself.
>> The only thing missing is the bind() behavior but, well, that's what
>> bind is for. If you need to bind arguments, just bind() your
>> arguments first.
>> On Jun 23, 8:25 am, Rick Waldron <waldron.r...@gmail.com> wrote:
>> > I detest the way setInterval() looks, so I came up with this... have
>> been
>> > using it my personal JS for some time.
>> > // usage:
>> > var _pollInt = 0;
>> > function repetiousPollFn() {
>> > console.log(_pollInt++);
>> > }
>> > repetiousPollFn.repeat(.5);
>> > Will, of course, repeat repetiousPollFn() every half second.
>> > Almost identical to .delay(), except that it returns setInterval instead
>> of
>> > setTimeout. One thing I intend to add is support for clearInterval,
>> however
>> > I figured I'd at least bring it up here first. I've never
>> > proposed/contributed here before (i'm a lurker of the list :D ) - any
>> > guidance is appreciated.
Just to clarify the above: Prototype Core already contains a similar
functionality: PeriodicalExecuter. The API is different but the
functionality is the same.
I'd strongly suggest looking into combining both approaches if you
want your suggestion to be included in core and not just stay a thread
in the mailing list. :)
Best,
Tobie
On Jun 24, 4:50 pm, Rick Waldron <waldron.r...@gmail.com> wrote:
> I've subbed my implementation with your to do some use-case testing. I'll
> report back anything of interest as I go along.
> Rick
> On Wed, Jun 24, 2009 at 10:49 AM, Rick Waldron <waldron.r...@gmail.com>wrote:
> > This is fantastic feedback - thanks!
> > On Wed, Jun 24, 2009 at 9:55 AM, Robert Kieffer <bro...@gmail.com> wrote:
> >> I can't say I'm a big fan of this. For several reasons.
> >> First, it's just a cosmetic replacement for setInterval(myfunction
> >> (...).bind(), ...) which simply isn't all that bad.
> >> Second, I'm not a fan of setInterval in general. I've seen some
> >> rather nasty behavior with calls queuing up if the invoked function
> >> takes longer than the delay to execute. In particular, this seems to
> >> be an issue if you do something like put a laptop to sleep. (But
> >> maybe others haven't seen this problem???) Thus, I prefer to use a
> >> self-invoking timeout like so:
> >> function myFunction() {
> >> // do stuff ...
> >> // call ourselves again
> >> if (/*we want to continue?*/) setTimeout(myFunction, 1000)
> >> }
> >> This doesn't call the function at exactly one second intervals, but
> >> that type of accuracy is rarely important. Instead, it guarantees you
> >> have at least one second of delay between invocations, which for
> >> distributing cpu load or polling (the more common cases where
> >> setInterval might be used), is more desireable.
> >> Finally, as Joe T. points out, there should be a way of cancelling the
> >> interval that doesn't require the user to store the returned value
> >> (*that* is what I find most annoying, not the syntax of
> >> "setInterval").
> >> var count = 0;
> >> function foo() {
> >> console.log(count++);
> >> return count < 10; // Return "false" when count >= 10 to cancel
> >> the repeat
> >> }
> >> // Start repeating 1/sec
> >> foo.repeat(1000);
> >> //... some time later change interval to 2/sec
> >> foo.repeat(500);
> >> // ... later still stop repeating.
> >> foo.stopRepeating();
> >> As you can see, this implementation of repeat() does a lot more for
> >> you than simply alias'ing "setInterval":
> >> - It guarantees your function is only invoked by one interval
> >> - It makes changing the interval or cancelling it altogether
> >> trivial.
> >> - It allows you to conditionally cancel the repeat from w/in the
> >> function itself.
> >> The only thing missing is the bind() behavior but, well, that's what
> >> bind is for. If you need to bind arguments, just bind() your
> >> arguments first.
> >> On Jun 23, 8:25 am, Rick Waldron <waldron.r...@gmail.com> wrote:
> >> > I detest the way setInterval() looks, so I came up with this... have
> >> been
> >> > using it my personal JS for some time.
> >> > Will, of course, repeat repetiousPollFn() every half second.
> >> > Almost identical to .delay(), except that it returns setInterval instead
> >> of
> >> > setTimeout. One thing I intend to add is support for clearInterval,
> >> however
> >> > I figured I'd at least bring it up here first. I've never
> >> > proposed/contributed here before (i'm a lurker of the list :D ) - any
> >> > guidance is appreciated.
I use Function.prototype.watch instead of Abstract.TimedObserver
Function.prototype.watch = function(delay,onChange){
var __method = this,
value = __method();
return setInterval(function(){
var v = __method();
if(v!==value){
onChange(v);
value = v;
}
},delay*1000);
};
May be you combine it too? =)
On Jun 24, 10:53 pm, Tobie Langel <tobie.lan...@gmail.com> wrote:
> Just to clarify the above: Prototype Core already contains a similar
> functionality: PeriodicalExecuter. The API is different but the
> functionality is the same.
> I'd strongly suggest looking into combining both approaches if you
> want your suggestion to be included in core and not just stay a thread
> in the mailing list. :)
> Best,
> Tobie
> On Jun 24, 4:50 pm, Rick Waldron <waldron.r...@gmail.com> wrote:
> > I've subbed my implementation with your to do some use-case testing. I'll
> > report back anything of interest as I go along.
> > Rick
> > On Wed, Jun 24, 2009 at 10:49 AM, Rick Waldron <waldron.r...@gmail.com>wrote:
> > > This is fantastic feedback - thanks!
> > > On Wed, Jun 24, 2009 at 9:55 AM, Robert Kieffer <bro...@gmail.com> wrote:
> > >> I can't say I'm a big fan of this. For several reasons.
> > >> First, it's just a cosmetic replacement for setInterval(myfunction
> > >> (...).bind(), ...) which simply isn't all that bad.
> > >> Second, I'm not a fan of setInterval in general. I've seen some
> > >> rather nasty behavior with calls queuing up if the invoked function
> > >> takes longer than the delay to execute. In particular, this seems to
> > >> be an issue if you do something like put a laptop to sleep. (But
> > >> maybe others haven't seen this problem???) Thus, I prefer to use a
> > >> self-invoking timeout like so:
> > >> function myFunction() {
> > >> // do stuff ...
> > >> // call ourselves again
> > >> if (/*we want to continue?*/) setTimeout(myFunction, 1000)
> > >> }
> > >> This doesn't call the function at exactly one second intervals, but
> > >> that type of accuracy is rarely important. Instead, it guarantees you
> > >> have at least one second of delay between invocations, which for
> > >> distributing cpu load or polling (the more common cases where
> > >> setInterval might be used), is more desireable.
> > >> Finally, as Joe T. points out, there should be a way of cancelling the
> > >> interval that doesn't require the user to store the returned value
> > >> (*that* is what I find most annoying, not the syntax of
> > >> "setInterval").
> > >> var count = 0;
> > >> function foo() {
> > >> console.log(count++);
> > >> return count < 10; // Return "false" when count >= 10 to cancel
> > >> the repeat
> > >> }
> > >> // Start repeating 1/sec
> > >> foo.repeat(1000);
> > >> //... some time later change interval to 2/sec
> > >> foo.repeat(500);
> > >> // ... later still stop repeating.
> > >> foo.stopRepeating();
> > >> As you can see, this implementation of repeat() does a lot more for
> > >> you than simply alias'ing "setInterval":
> > >> - It guarantees your function is only invoked by one interval
> > >> - It makes changing the interval or cancelling it altogether
> > >> trivial.
> > >> - It allows you to conditionally cancel the repeat from w/in the
> > >> function itself.
> > >> The only thing missing is the bind() behavior but, well, that's what
> > >> bind is for. If you need to bind arguments, just bind() your
> > >> arguments first.
> > >> On Jun 23, 8:25 am, Rick Waldron <waldron.r...@gmail.com> wrote:
> > >> > I detest the way setInterval() looks, so I came up with this... have
> > >> been
> > >> > using it my personal JS for some time.
> > >> > Will, of course, repeat repetiousPollFn() every half second.
> > >> > Almost identical to .delay(), except that it returns setInterval instead
> > >> of
> > >> > setTimeout. One thing I intend to add is support for clearInterval,
> > >> however
> > >> > I figured I'd at least bring it up here first. I've never
> > >> > proposed/contributed here before (i'm a lurker of the list :D ) - any
> > >> > guidance is appreciated.
FWIW, PeriodicalExecuter has always struck me as a bit of a wart on
the Prototype API. The name and usage are awkward, and it's
functionality really feels like something that should just be a
Function extension, as we're seeing in this thread. I'm assuming it's
presence is mostly a legacy thing.
But... I'm not really arguing for it's removal. Just pissing into the
wind. :-)
On Jun 24, 9:53 am, Tobie Langel <tobie.lan...@gmail.com> wrote:
> Just to clarify the above: Prototype Core already contains a similar
> functionality: PeriodicalExecuter. The API is different but the
> functionality is the same.
> I'd strongly suggest looking into combining both approaches if you
> want your suggestion to be included in core and not just stay a thread
> in the mailing list. :)
I had in fact looked into PeriodicalExecuter and to be perfectly honest,
with no offense intended, i think it's usage syntax is hideous which is what
led me to writing my own Function.prototype method instead, taking
inspiration from .delay()
It doesnt matter to me whether or not .repeat() makes it into the prototype
core - I will always have it at my disposal, I simply wanted to share the
concept with the group.
I think everything I've said sounds like I'm in a bad mood, sorry about
that! :D
Rick
On Wed, Jun 24, 2009 at 12:53 PM, Tobie Langel <tobie.lan...@gmail.com>wrote:
> Just to clarify the above: Prototype Core already contains a similar
> functionality: PeriodicalExecuter. The API is different but the
> functionality is the same.
> I'd strongly suggest looking into combining both approaches if you
> want your suggestion to be included in core and not just stay a thread
> in the mailing list. :)
> Best,
> Tobie
> On Jun 24, 4:50 pm, Rick Waldron <waldron.r...@gmail.com> wrote:
> > I've subbed my implementation with your to do some use-case testing. I'll
> > report back anything of interest as I go along.
> > Rick
> > On Wed, Jun 24, 2009 at 10:49 AM, Rick Waldron <waldron.r...@gmail.com
> >wrote:
> > > This is fantastic feedback - thanks!
> > > On Wed, Jun 24, 2009 at 9:55 AM, Robert Kieffer <bro...@gmail.com>
> wrote:
> > >> I can't say I'm a big fan of this. For several reasons.
> > >> First, it's just a cosmetic replacement for setInterval(myfunction
> > >> (...).bind(), ...) which simply isn't all that bad.
> > >> Second, I'm not a fan of setInterval in general. I've seen some
> > >> rather nasty behavior with calls queuing up if the invoked function
> > >> takes longer than the delay to execute. In particular, this seems to
> > >> be an issue if you do something like put a laptop to sleep. (But
> > >> maybe others haven't seen this problem???) Thus, I prefer to use a
> > >> self-invoking timeout like so:
> > >> function myFunction() {
> > >> // do stuff ...
> > >> // call ourselves again
> > >> if (/*we want to continue?*/) setTimeout(myFunction, 1000)
> > >> }
> > >> This doesn't call the function at exactly one second intervals, but
> > >> that type of accuracy is rarely important. Instead, it guarantees you
> > >> have at least one second of delay between invocations, which for
> > >> distributing cpu load or polling (the more common cases where
> > >> setInterval might be used), is more desireable.
> > >> Finally, as Joe T. points out, there should be a way of cancelling the
> > >> interval that doesn't require the user to store the returned value
> > >> (*that* is what I find most annoying, not the syntax of
> > >> "setInterval").
> > >> var count = 0;
> > >> function foo() {
> > >> console.log(count++);
> > >> return count < 10; // Return "false" when count >= 10 to cancel
> > >> the repeat
> > >> }
> > >> // Start repeating 1/sec
> > >> foo.repeat(1000);
> > >> //... some time later change interval to 2/sec
> > >> foo.repeat(500);
> > >> // ... later still stop repeating.
> > >> foo.stopRepeating();
> > >> As you can see, this implementation of repeat() does a lot more for
> > >> you than simply alias'ing "setInterval":
> > >> - It guarantees your function is only invoked by one interval
> > >> - It makes changing the interval or cancelling it altogether
> > >> trivial.
> > >> - It allows you to conditionally cancel the repeat from w/in the
> > >> function itself.
> > >> The only thing missing is the bind() behavior but, well, that's what
> > >> bind is for. If you need to bind arguments, just bind() your
> > >> arguments first.
> > >> On Jun 23, 8:25 am, Rick Waldron <waldron.r...@gmail.com> wrote:
> > >> > I detest the way setInterval() looks, so I came up with this... have
> > >> been
> > >> > using it my personal JS for some time.
> > >> > Will, of course, repeat repetiousPollFn() every half second.
> > >> > Almost identical to .delay(), except that it returns setInterval
> instead
> > >> of
> > >> > setTimeout. One thing I intend to add is support for clearInterval,
> > >> however
> > >> > I figured I'd at least bring it up here first. I've never
> > >> > proposed/contributed here before (i'm a lurker of the list :D ) -
> any
> > >> > guidance is appreciated.
Fully agree regarding PE. It does however handle issues a regular
setInterval doesn't (as you mentioned).
It's clearly an area which would need refinement, but that's better
done in a backwards compatible way.
Personally, I'd love to see PE implemented as a method of Function
instances.
So since this is the core mailing list, I'm trying to give directions
on how it could be best implemented given legacy constraints and
consistency with the rest of the API.
Clearly, consistency with Function#defer and Function#delay would
imply returning a setInterval index. Unfortunately, since setTimeout
is used instead of setInterval, this isn't possible.
Maybe the simplest solution would be to make Function#repeat return an
instance of PE. Implementation would then be roughly:
Function.prototype.repeat = function(interval) {
return new PeriodicalExecuter(this, interval);
}
Note that in that case, modifying Function#delay and Function#defer to
return a PE-like object instance with a stop method would make more
sense API wise, but at the expense of a larger memory footprint and
backwards compatibility.
As you can see, making the right choice isn't simple.
Best,
Tobie
On Jun 24, 11:28 pm, Rick Waldron <waldron.r...@gmail.com> wrote:
> I had in fact looked into PeriodicalExecuter and to be perfectly honest,
> with no offense intended, i think it's usage syntax is hideous which is what
> led me to writing my own Function.prototype method instead, taking
> inspiration from .delay()
> It doesnt matter to me whether or not .repeat() makes it into the prototype
> core - I will always have it at my disposal, I simply wanted to share the
> concept with the group.
> I think everything I've said sounds like I'm in a bad mood, sorry about
> that! :D
> Rick
> On Wed, Jun 24, 2009 at 12:53 PM, Tobie Langel <tobie.lan...@gmail.com>wrote:
> > Just to clarify the above: Prototype Core already contains a similar
> > functionality: PeriodicalExecuter. The API is different but the
> > functionality is the same.
> > I'd strongly suggest looking into combining both approaches if you
> > want your suggestion to be included in core and not just stay a thread
> > in the mailing list. :)
> > Best,
> > Tobie
> > On Jun 24, 4:50 pm, Rick Waldron <waldron.r...@gmail.com> wrote:
> > > I've subbed my implementation with your to do some use-case testing. I'll
> > > report back anything of interest as I go along.
> > > Rick
> > > On Wed, Jun 24, 2009 at 10:49 AM, Rick Waldron <waldron.r...@gmail.com
> > >wrote:
> > > > This is fantastic feedback - thanks!
> > > > On Wed, Jun 24, 2009 at 9:55 AM, Robert Kieffer <bro...@gmail.com>
> > wrote:
> > > >> I can't say I'm a big fan of this. For several reasons.
> > > >> First, it's just a cosmetic replacement for setInterval(myfunction
> > > >> (...).bind(), ...) which simply isn't all that bad.
> > > >> Second, I'm not a fan of setInterval in general. I've seen some
> > > >> rather nasty behavior with calls queuing up if the invoked function
> > > >> takes longer than the delay to execute. In particular, this seems to
> > > >> be an issue if you do something like put a laptop to sleep. (But
> > > >> maybe others haven't seen this problem???) Thus, I prefer to use a
> > > >> self-invoking timeout like so:
> > > >> function myFunction() {
> > > >> // do stuff ...
> > > >> // call ourselves again
> > > >> if (/*we want to continue?*/) setTimeout(myFunction, 1000)
> > > >> }
> > > >> This doesn't call the function at exactly one second intervals, but
> > > >> that type of accuracy is rarely important. Instead, it guarantees you
> > > >> have at least one second of delay between invocations, which for
> > > >> distributing cpu load or polling (the more common cases where
> > > >> setInterval might be used), is more desireable.
> > > >> Finally, as Joe T. points out, there should be a way of cancelling the
> > > >> interval that doesn't require the user to store the returned value
> > > >> (*that* is what I find most annoying, not the syntax of
> > > >> "setInterval").
> > > >> var count = 0;
> > > >> function foo() {
> > > >> console.log(count++);
> > > >> return count < 10; // Return "false" when count >= 10 to cancel
> > > >> the repeat
> > > >> }
> > > >> // Start repeating 1/sec
> > > >> foo.repeat(1000);
> > > >> //... some time later change interval to 2/sec
> > > >> foo.repeat(500);
> > > >> // ... later still stop repeating.
> > > >> foo.stopRepeating();
> > > >> As you can see, this implementation of repeat() does a lot more for
> > > >> you than simply alias'ing "setInterval":
> > > >> - It guarantees your function is only invoked by one interval
> > > >> - It makes changing the interval or cancelling it altogether
> > > >> trivial.
> > > >> - It allows you to conditionally cancel the repeat from w/in the
> > > >> function itself.
> > > >> The only thing missing is the bind() behavior but, well, that's what
> > > >> bind is for. If you need to bind arguments, just bind() your
> > > >> arguments first.
> > > >> On Jun 23, 8:25 am, Rick Waldron <waldron.r...@gmail.com> wrote:
> > > >> > I detest the way setInterval() looks, so I came up with this... have
> > > >> been
> > > >> > using it my personal JS for some time.
> > > >> > Will, of course, repeat repetiousPollFn() every half second.
> > > >> > Almost identical to .delay(), except that it returns setInterval
> > instead
> > > >> of
> > > >> > setTimeout. One thing I intend to add is support for clearInterval,
> > > >> however
> > > >> > I figured I'd at least bring it up here first. I've never
> > > >> > proposed/contributed here before (i'm a lurker of the list :D ) -
> > any
> > > >> > guidance is appreciated.
This repeat() method def is 775Bytes, accepts arguments like delay/defer,
uses setTimeout (returns initial setTimeout index) and has a stopping
mechanism.
Rick
On Wed, Jun 24, 2009 at 10:04 PM, Tobie Langel <tobie.lan...@gmail.com>wrote:
> Fully agree regarding PE. It does however handle issues a regular
> setInterval doesn't (as you mentioned).
> It's clearly an area which would need refinement, but that's better
> done in a backwards compatible way.
> Personally, I'd love to see PE implemented as a method of Function
> instances.
> So since this is the core mailing list, I'm trying to give directions
> on how it could be best implemented given legacy constraints and
> consistency with the rest of the API.
> Clearly, consistency with Function#defer and Function#delay would
> imply returning a setInterval index. Unfortunately, since setTimeout
> is used instead of setInterval, this isn't possible.
> Maybe the simplest solution would be to make Function#repeat return an
> instance of PE. Implementation would then be roughly:
> Note that in that case, modifying Function#delay and Function#defer to
> return a PE-like object instance with a stop method would make more
> sense API wise, but at the expense of a larger memory footprint and
> backwards compatibility.
> As you can see, making the right choice isn't simple.
> Best,
> Tobie
> On Jun 24, 11:28 pm, Rick Waldron <waldron.r...@gmail.com> wrote:
> > Tobie,
> > I had in fact looked into PeriodicalExecuter and to be perfectly honest,
> > with no offense intended, i think it's usage syntax is hideous which is
> what
> > led me to writing my own Function.prototype method instead, taking
> > inspiration from .delay()
> > It doesnt matter to me whether or not .repeat() makes it into the
> prototype
> > core - I will always have it at my disposal, I simply wanted to share the
> > concept with the group.
> > I think everything I've said sounds like I'm in a bad mood, sorry about
> > that! :D
> > Rick
> > On Wed, Jun 24, 2009 at 12:53 PM, Tobie Langel <tobie.lan...@gmail.com
> >wrote:
> > > Just to clarify the above: Prototype Core already contains a similar
> > > functionality: PeriodicalExecuter. The API is different but the
> > > functionality is the same.
> > > I'd strongly suggest looking into combining both approaches if you
> > > want your suggestion to be included in core and not just stay a thread
> > > in the mailing list. :)
> > > Best,
> > > Tobie
> > > On Jun 24, 4:50 pm, Rick Waldron <waldron.r...@gmail.com> wrote:
> > > > I've subbed my implementation with your to do some use-case testing.
> I'll
> > > > report back anything of interest as I go along.
> > > > Rick
> > > > On Wed, Jun 24, 2009 at 10:49 AM, Rick Waldron <
> waldron.r...@gmail.com
> > > >wrote:
> > > > > This is fantastic feedback - thanks!
> > > > > On Wed, Jun 24, 2009 at 9:55 AM, Robert Kieffer <bro...@gmail.com>
> > > wrote:
> > > > >> I can't say I'm a big fan of this. For several reasons.
> > > > >> First, it's just a cosmetic replacement for setInterval(myfunction
> > > > >> (...).bind(), ...) which simply isn't all that bad.
> > > > >> Second, I'm not a fan of setInterval in general. I've seen some
> > > > >> rather nasty behavior with calls queuing up if the invoked
> function
> > > > >> takes longer than the delay to execute. In particular, this seems
> to
> > > > >> be an issue if you do something like put a laptop to sleep. (But
> > > > >> maybe others haven't seen this problem???) Thus, I prefer to use
> a
> > > > >> self-invoking timeout like so:
> > > > >> function myFunction() {
> > > > >> // do stuff ...
> > > > >> // call ourselves again
> > > > >> if (/*we want to continue?*/) setTimeout(myFunction, 1000)
> > > > >> }
> > > > >> This doesn't call the function at exactly one second intervals,
> but
> > > > >> that type of accuracy is rarely important. Instead, it guarantees
> you
> > > > >> have at least one second of delay between invocations, which for
> > > > >> distributing cpu load or polling (the more common cases where
> > > > >> setInterval might be used), is more desireable.
> > > > >> Finally, as Joe T. points out, there should be a way of cancelling
> the
> > > > >> interval that doesn't require the user to store the returned value
> > > > >> (*that* is what I find most annoying, not the syntax of
> > > > >> "setInterval").
> > > > >> // Start repeating 1/sec
> > > > >> foo.repeat(1000);
> > > > >> //... some time later change interval to 2/sec
> > > > >> foo.repeat(500);
> > > > >> // ... later still stop repeating.
> > > > >> foo.stopRepeating();
> > > > >> As you can see, this implementation of repeat() does a lot more
> for
> > > > >> you than simply alias'ing "setInterval":
> > > > >> - It guarantees your function is only invoked by one interval
> > > > >> - It makes changing the interval or cancelling it altogether
> > > > >> trivial.
> > > > >> - It allows you to conditionally cancel the repeat from w/in the
> > > > >> function itself.
> > > > >> The only thing missing is the bind() behavior but, well, that's
> what
> > > > >> bind is for. If you need to bind arguments, just bind() your
> > > > >> arguments first.
> > > > >> On Jun 23, 8:25 am, Rick Waldron <waldron.r...@gmail.com> wrote:
> > > > >> > I detest the way setInterval() looks, so I came up with this...
> have
> > > > >> been
> > > > >> > using it my personal JS for some time.
> > > > >> > Will, of course, repeat repetiousPollFn() every half second.
> > > > >> > Almost identical to .delay(), except that it returns setInterval
> > > instead
> > > > >> of
> > > > >> > setTimeout. One thing I intend to add is support for
> clearInterval,
> > > > >> however
> > > > >> > I figured I'd at least bring it up here first. I've never
> > > > >> > proposed/contributed here before (i'm a lurker of the list :D )
> -
> > > any
> > > > >> > guidance is appreciated.
Passing arguments would require some simple currying:
Function.prototype.repeat = function(interval) {
var fn = this;
if (arguments.length > 1) {
// not testsed but you get the idea
fn = fn.curry.apply(fn, Array.prototype.slice.call(arguments, 1));
}
return new PeriodicalExecuter(fn, interval);
}
> This may come to you twice, but this is slightly updated:
> This repeat() method def is 775Bytes, accepts arguments like delay/defer,
> uses setTimeout (returns initial setTimeout index) and has a stopping
> mechanism.
What's the point in returning setTimeout index? That will set
expectations which can't be met: developers will expect to be able to
stop the functions calls by clearing it.
Are you sure your proposal fixes all of the small issues PE fixes? For
example, does it guarantee that the function will continue being
called if it happens to once throw an error. Does it avoid calling the
function again if a previous function is still executing, etc.?
I understand your eagerness to move away from a model you dislike, but
that shouldn't make you throw away all of the work that's been put
into previous solutions.
FWIW, I just noticed a patch wasn't applied to PE in current trunk
(it's missing a throw statement).
> Function.prototype.repeat = function(interval) {
> var fn = this;
> if (arguments.length > 1) {
> // not testsed but you get the idea
> fn = fn.curry.apply(fn, Array.prototype.slice.call(arguments, 1));
> }
> return new PeriodicalExecuter(fn, interval);
> }
If sticking to the PE approach there's no internal self-stop mechanism
(is there?), which i see as a nice touch in the above proposal (for
what my opinion is worth).
What about (from 1.6.1_rc2):
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
if (this.execute()===false) // MOD
this.stop(); // NEW
} catch(e) {
/* empty catch for clients that don't support try/finally */
}
finally {
this.currentlyExecuting = false;
}
}
}
Just tossing in my 2 cents because i'm intrigued by that feature.
-joe t.
On Jun 26, 6:02 am, Tobie Langel <tobie.lan...@gmail.com> wrote:
> Passing arguments would require some simple currying:
> Function.prototype.repeat = function(interval) {
> var fn = this;
> if (arguments.length > 1) {
> // not testsed but you get the idea
> fn = fn.curry.apply(fn, Array.prototype.slice.call(arguments, 1));
> }
> return new PeriodicalExecuter(fn, interval);
> }
> > This may come to you twice, but this is slightly updated:
> > This repeat() method def is 775Bytes, accepts arguments like delay/defer,
> > uses setTimeout (returns initial setTimeout index) and has a stopping
> > mechanism.
> What's the point in returning setTimeout index? That will set
> expectations which can't be met: developers will expect to be able to
> stop the functions calls by clearing it.
> Are you sure your proposal fixes all of the small issues PE fixes? For
> example, does it guarantee that the function will continue being
> called if it happens to once throw an error. Does it avoid calling the
> function again if a previous function is still executing, etc.?
> I understand your eagerness to move away from a model you dislike, but
> that shouldn't make you throw away all of the work that's been put
> into previous solutions.
> FWIW, I just noticed a patch wasn't applied to PE in current trunk
> (it's missing a throw statement).
> Tobie,
>> Function.prototype.repeat = function(interval) {
>> var fn = this;
>> if (arguments.length > 1) {
>> // not testsed but you get the idea
>> fn = fn.curry.apply(fn, Array.prototype.slice.call(arguments, 1));
>> }
>> return new PeriodicalExecuter(fn, interval);
>> }
> If sticking to the PE approach there's no internal self-stop mechanism
> (is there?), which i see as a nice touch in the above proposal (for
> what my opinion is worth).
> What about (from 1.6.1_rc2):
> onTimerEvent: function() {
> if (!this.currentlyExecuting) {
> try {
> this.currentlyExecuting = true;
> if (this.execute()===false) // MOD
> this.stop(); // NEW
> } catch(e) {
> /* empty catch for clients that don't support try/finally */
> }
> finally {
> this.currentlyExecuting = false;
> }
> }
> }
> Just tossing in my 2 cents because i'm intrigued by that feature.
> -joe t.
> On Jun 26, 6:02 am, Tobie Langel <tobie.lan...@gmail.com> wrote:
>>> How to stop it? arguments?
>> Stopping it is as easy as:
>> pe = foo.repeat();
>> pe.stop();
>> Passing arguments would require some simple currying:
>> Function.prototype.repeat = function(interval) {
>> var fn = this;
>> if (arguments.length > 1) {
>> // not testsed but you get the idea
>> fn = fn.curry.apply(fn, Array.prototype.slice.call(arguments, 1));
>> }
>> return new PeriodicalExecuter(fn, interval);
>> }
>>> This may come to you twice, but this is slightly updated:
>>> This repeat() method def is 775Bytes, accepts arguments like delay/ >>> defer,
>>> uses setTimeout (returns initial setTimeout index) and has a
>>> stopping
>>> mechanism.
>> What's the point in returning setTimeout index? That will set
>> expectations which can't be met: developers will expect to be able to
>> stop the functions calls by clearing it.
>> Are you sure your proposal fixes all of the small issues PE fixes?
>> For
>> example, does it guarantee that the function will continue being
>> called if it happens to once throw an error. Does it avoid calling
>> the
>> function again if a previous function is still executing, etc.?
>> I understand your eagerness to move away from a model you dislike,
>> but
>> that shouldn't make you throw away all of the work that's been put
>> into previous solutions.
>> FWIW, I just noticed a patch wasn't applied to PE in current trunk
>> (it's missing a throw statement).
Weighing in... First off, love the idea of Function#repeat.
Wonderfully simple and expressive.
As Tobie says, the goals when doing it should be to handle all of the
issues PE already handles, to reuse existing code, and to be
consistent with other API functions.
Some notes:
1. I'd avoid requiring #curry or #bind on top of #repeat; #repeat
should be able to handle arguments and context itself. Every curry at
least doubles the call overhead.
2. Optional context would be helpful:
Function#delay(options[, args...]) -> Number
...with `options` being either a number (frequency) or an object with
`context` and `frequency` parameters; the latter allows repeating
method calls.
3. #1 suggests that rather than #repeat using PE, the guts of PE
should become #repeat and the PE should use it:
4. I'd like to be able to repeat functions not explicitly designed to
#repeat, which suggests not changing their signature. Perhaps the self-
stop mechanism could remain a feature that PE adds on top of #repeat
(at the cost that PE functions have to be explicitly intended to be
repeated [or must ignore their args], as is currently the case).
5. Like Robert, I prefer the self-repeat over setInterval (that's
always how I do it), but unless we've seen significant issues with
setInterval we should be wary of changing it, especially in light of
how doing so complicates the API (e.g., return value issues). Perhaps
this aspect is a separate question entirely.
6. If we do need to use something other than an interval handle as the
return value, I'd suggest providing a stop function that works with
both interval handles and whatever our new thing is, e.g.:
Function.stop = function(handle) {
if (typeof handle == 'number') {
clearInterval(handle);
}
else {
/* ...stop it the new way... */
}
};
@Rick: All of this discussion probably seems like nit-picking your
idea to death. In fact, I think it indicates that there's a lot of
support and appreciation for your idea, and we're all (well, nearly
all, there's a dissenter) just trying to make it fit in, and make it
as cool as the idea warrants.
--
T.J. Crowder
tj / crowder software / com
On Aug 26, 3:33 am, Samuel Lebeau <samuel.leb...@gmail.com> wrote:
> Callback function receives PE instance as first argument, so here
> would be the self-stop mechanism :
> function(executer) { executer.stop() }.repeat()
> Best,
> Samuel.
> On 26 juin 09, at 15:46, joe t. wrote:
> > Tobie,
> >> Function.prototype.repeat = function(interval) {
> >> var fn = this;
> >> if (arguments.length > 1) {
> >> // not testsed but you get the idea
> >> fn = fn.curry.apply(fn, Array.prototype.slice.call(arguments, 1));
> >> }
> >> return new PeriodicalExecuter(fn, interval);
> >> }
> > If sticking to the PE approach there's no internal self-stop mechanism
> > (is there?), which i see as a nice touch in the above proposal (for
> > what my opinion is worth).
> > What about (from 1.6.1_rc2):
> > onTimerEvent: function() {
> > if (!this.currentlyExecuting) {
> > try {
> > this.currentlyExecuting = true;
> > if (this.execute()===false) // MOD
> > this.stop(); // NEW
> > } catch(e) {
> > /* empty catch for clients that don't support try/finally */
> > }
> > finally {
> > this.currentlyExecuting = false;
> > }
> > }
> > }
> > Just tossing in my 2 cents because i'm intrigued by that feature.
> > -joe t.
> > On Jun 26, 6:02 am, Tobie Langel <tobie.lan...@gmail.com> wrote:
> >>> How to stop it? arguments?
> >> Stopping it is as easy as:
> >> pe = foo.repeat();
> >> pe.stop();
> >> Passing arguments would require some simple currying:
> >> Function.prototype.repeat = function(interval) {
> >> var fn = this;
> >> if (arguments.length > 1) {
> >> // not testsed but you get the idea
> >> fn = fn.curry.apply(fn, Array.prototype.slice.call(arguments, 1));
> >> }
> >> return new PeriodicalExecuter(fn, interval);
> >> }
> >>> This may come to you twice, but this is slightly updated:
> >>> This repeat() method def is 775Bytes, accepts arguments like delay/
> >>> defer,
> >>> uses setTimeout (returns initial setTimeout index) and has a
> >>> stopping
> >>> mechanism.
> >> What's the point in returning setTimeout index? That will set
> >> expectations which can't be met: developers will expect to be able to
> >> stop the functions calls by clearing it.
> >> Are you sure your proposal fixes all of the small issues PE fixes?
> >> For
> >> example, does it guarantee that the function will continue being
> >> called if it happens to once throw an error. Does it avoid calling
> >> the
> >> function again if a previous function is still executing, etc.?
> >> I understand your eagerness to move away from a model you dislike,
> >> but
> >> that shouldn't make you throw away all of the work that's been put
> >> into previous solutions.
> >> FWIW, I just noticed a patch wasn't applied to PE in current trunk
> >> (it's missing a throw statement).
Your goals sound about right. Implicit in there, I think, is "make it easy to deprecate PE at some later date". At least, that's how I read it. :)
Re: #2 - Why not just use bind() to provide context? I've never been a fan of overloading arguments with multiple interpretations. 'Gets too confusing, and makes the implementation that much uglier.
Re: #4 - I feel the ability to self-stop is more important than being able to repeat() functions that aren't designed for it. I _really_ feel that making the self-stop behavior an optional add-on feature of PE is a bad idea. self-stop is an elegant pattern (IMHO) so forcing users to go through the awkward PE API to get at it doesn't make sense. Also, it makes deprecating PE harder.
***Hmm...*** How about this as a solution: Instead of having a function return false to stop, have it "throw $break"! I think that addresses your concern, and is consistent with how Prototype does this sort of thing elsewhere (in Enumerable).
> Your goals sound about right. Implicit in there, I think, is "make it easy
> to deprecate PE at some later date". At least, that's how I read it. :)
> Re: #2 - Why not just use bind() to provide context? I've never been a fan
> of overloading arguments with multiple interpretations. 'Gets too
> confusing, and makes the implementation that much uglier.
> Re: #4 - I feel the ability to self-stop is more important than being able
> to repeat() functions that aren't designed for it. I _really_ feel that
> making the self-stop behavior an optional add-on feature of PE is a bad
> idea. self-stop is an elegant pattern (IMHO) so forcing users to go through
> the awkward PE API to get at it doesn't make sense. Also, it makes
> deprecating PE harder.
> ***Hmm...*** How about this as a solution: Instead of having a function
> return false to stop, have it "throw $break"! I think that addresses your
> concern, and is consistent with how Prototype does this sort of thing
> elsewhere (in Enumerable).
> It's true, I was thinking in terms of deprecating PE at some
> stage... :-)
> Re #2: Using #bind at least doubles the call overhead, which I'm not a
> fan of generally.
> > ...have it "throw $break"!
> Now that is a very smart idea.
> --
> T.J. Crowder
> tj / crowder software / com
> On Aug 27, 4:13 pm, Robert Kieffer <bro...@gmail.com> wrote:
> > @TJ...
> > Your goals sound about right. Implicit in there, I think, is "make it easy
> > to deprecate PE at some later date". At least, that's how I read it. :)
> > Re: #2 - Why not just use bind() to provide context? I've never been a fan
> > of overloading arguments with multiple interpretations. 'Gets too
> > confusing, and makes the implementation that much uglier.
> > Re: #4 - I feel the ability to self-stop is more important than being able
> > to repeat() functions that aren't designed for it. I _really_ feel that
> > making the self-stop behavior an optional add-on feature of PE is a bad
> > idea. self-stop is an elegant pattern (IMHO) so forcing users to go through
> > the awkward PE API to get at it doesn't make sense. Also, it makes
> > deprecating PE harder.
> > ***Hmm...*** How about this as a solution: Instead of having a function
> > return false to stop, have it "throw $break"! I think that addresses your
> > concern, and is consistent with how Prototype does this sort of thing
> > elsewhere (in Enumerable).
Re: @Rick: All of this discussion probably seems like nit-picking your
idea to death. In fact, I think it indicates that there's a lot of
support and appreciation for your idea, and we're all (well, nearly
all, there's a dissenter) just trying to make it fit in, and make it
as cool as the idea warrants.
I love it! How else are we going to make a good idea into an awesome idea?
Such is why i brought it to the group - I'm just pleased that it wasn't
discarded. I'm excited to see the process of it's evolution and hope it
continues to do so and eventually to see Function#repeat() make its way into
Prototype - but only the best possible version of the method!
On Thu, Aug 27, 2009 at 11:13 AM, Robert Kieffer <bro...@gmail.com> wrote:
> @TJ...
> Your goals sound about right. Implicit in there, I think, is "make it easy
> to deprecate PE at some later date". At least, that's how I read it. :)
> Re: #2 - Why not just use bind() to provide context? I've never been a
> fan of overloading arguments with multiple interpretations. 'Gets too
> confusing, and makes the implementation that much uglier.
> Re: #4 - I feel the ability to self-stop is more important than being able
> to repeat() functions that aren't designed for it. I _really_ feel that
> making the self-stop behavior an optional add-on feature of PE is a bad
> idea. self-stop is an elegant pattern (IMHO) so forcing users to go through
> the awkward PE API to get at it doesn't make sense. Also, it makes
> deprecating PE harder.
> ***Hmm...*** How about this as a solution: Instead of having a function
> return false to stop, have it "throw $break"! I think that addresses your
> concern, and is consistent with how Prototype does this sort of thing
> elsewhere (in Enumerable).
*blech* to ES5's enumerable stuff not having $break or similar
functionality. I've just read the forEach section of the draft spec
from a while back, and I'm not seeing a discussion of exception
handling. I haven't delved deep, though -- do you know offhand how
exceptions in the callback function are handled? E.g, can one
implement one's own $break handling, or are exceptions eaten?
Re setInterval and setTimeout, how do you see implementing #delay or
similar without using them? Or do you not see it, e.g., a pure LANG
version of Prototype wouldn't have Function#defer.
--
T.J. Crowder
tj / crowder software / com
On Aug 27, 6:08 pm, Rick Waldron <waldron.r...@gmail.com> wrote:
> Re: @Rick: All of this discussion probably seems like nit-picking your
> idea to death. In fact, I think it indicates that there's a lot of
> support and appreciation for your idea, and we're all (well, nearly
> all, there's a dissenter) just trying to make it fit in, and make it
> as cool as the idea warrants.
> I love it! How else are we going to make a good idea into an awesome idea?
> Such is why i brought it to the group - I'm just pleased that it wasn't
> discarded. I'm excited to see the process of it's evolution and hope it
> continues to do so and eventually to see Function#repeat() make its way into
> Prototype - but only the best possible version of the method!
> On Thu, Aug 27, 2009 at 11:13 AM, Robert Kieffer <bro...@gmail.com> wrote:
> > @TJ...
> > Your goals sound about right. Implicit in there, I think, is "make it easy
> > to deprecate PE at some later date". At least, that's how I read it. :)
> > Re: #2 - Why not just use bind() to provide context? I've never been a
> > fan of overloading arguments with multiple interpretations. 'Gets too
> > confusing, and makes the implementation that much uglier.
> > Re: #4 - I feel the ability to self-stop is more important than being able
> > to repeat() functions that aren't designed for it. I _really_ feel that
> > making the self-stop behavior an optional add-on feature of PE is a bad
> > idea. self-stop is an elegant pattern (IMHO) so forcing users to go through
> > the awkward PE API to get at it doesn't make sense. Also, it makes
> > deprecating PE harder.
> > ***Hmm...*** How about this as a solution: Instead of having a function
> > return false to stop, have it "throw $break"! I think that addresses your
> > concern, and is consistent with how Prototype does this sort of thing
> > elsewhere (in Enumerable).
> *blech* to ES5's enumerable stuff not having $break or similar
> functionality. I've just read the forEach section of the draft spec
> from a while back, and I'm not seeing a discussion of exception
> handling. I haven't delved deep, though -- do you know offhand how
> exceptions in the callback function are handled? E.g, can one
> implement one's own $break handling, or are exceptions eaten?
Exceptions aren't eaten.
> Re setInterval and setTimeout, how do you see implementing #delay or
> similar without using them?
You can't.
> Or do you not see it, e.g., a pure LANG
> version of Prototype wouldn't have Function#defer.
Maybe Function#defer would be defined only if window.setTimeout was
present.
> > *blech* to ES5's enumerable stuff not having $break or similar
> > functionality. I've just read the forEach section of the draft spec
> > from a while back, and I'm not seeing a discussion of exception
> > handling. I haven't delved deep, though -- do you know offhand how
> > exceptions in the callback function are handled? E.g, can one
> > implement one's own $break handling, or are exceptions eaten?
> Exceptions aren't eaten.
> > Re setInterval and setTimeout, how do you see implementing #delay or
> > similar without using them?
> You can't.
> > Or do you not see it, e.g., a pure LANG
> > version of Prototype wouldn't have Function#defer.
> Maybe Function#defer would be defined only if window.setTimeout was
> present.
Unfortunately for me, i don't offer much on the deeply technical side,
but want to offer my vote to explore this idea. The self-stop is
definitely an attractive feature, and while the examples that i've
seen in this thread show a stop-on-return-false, it would probably be
more correct to stop-on-provided-condition:
[snipped from Robert's post]
Object.extend(Function.prototype, {
repeat: function(delay, stopCondition) {
this.stopCondition = typeof stopCondition == "function" ?
stopCondition : function(test){return test ===
stopCondition;}; // or $break-like mechanism?
...
if (!this._repeater) this._repeater = function() {
// Let _method cancel repeat by testing against stopCondition
if (!this.stopCondition(_method())) setTimeout
(_method._repeater, delay);
}
...
[/snip]
i'm obviously no expert. Robert mentions not being a fan of argument
interpretation, which makes sense. But in this case, the only
"exception" is for a function, and only occurs when the repeat is
created. And one strike against the above is if the user provides a
time-consuming stopCondition function, it increases the time to the
next repeat. Unless some timing math is done on either side of the
stopCondition call to balance the setTimeout delay:
...which is bad when the time differential is > delay. :(
For what it's worth, i'd like to see allowance of any object type to
be the stop condition, but if there are greater issues preventing
that, i defer to the better judgment of the developers. :)
@tobie: I'm a little unclear how the ES5 implementation of forEach()
impacts the idea of using $break to terminate a repeat() call. Can
you elaborate?
Unless $break is removed from Prototype altogether, I don't see how
this is an issue. And the only reason to remove $break is if all the
Enumerable methods (that depend on it) are also going away. But given
that a) ES5 doesn't support a mechanism for early termination of
forEach(), b) the "throw $break" pattern is both useful and c) ES5
doesn't support many of the Enumerable methods, it seems like those
methods will stick around and continue to recognize $break as a way of
terminating an enumeration.