[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
Hi all, 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: var PeriodicalExecuter = Class.create({ initialize: function(callback, frequency) { this.handle = callback.repeat(frequency, this); }, stop: function() { if (this.handle) { clearInterval(this.handle); this.handle = 0; } } }); 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: Joe, 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: http://jsbin.com/opimu 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
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
@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). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
Hey Robert, 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). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
Food for thought: 1. We would like to completely decouple native and host objects in the LANG section for version 1.7. `setTimeout` and `setInterval` are host objects... 2. We're planning strict ES 5 compliance of enumerables for 1.7. that implies removing $break. Best, Tobie On Aug 27, 5:29 pm, T.J. Crowder t...@crowdersoftware.com wrote: Hey Robert, 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). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
*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. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
Exceptions aren't eaten. Good, so a $break-like mechanism is possible then, just moved out a level. -- T.J. On Aug 27, 10:49 pm, Tobie Langel tobie.lan...@gmail.com wrote: *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. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
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: http://jsbin.com/opimu 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). Best, Tobie --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
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: http://jsbin.com/opimu 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). Best, Tobie --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...]) -- Revised from Robert's version
Rick, Maybe i'm missing how that revision works, but it appears to me that your stop property doesn't actually stop the repeater. Your stop returns before further execution happens, but the timeout ID for the window still exists. What am i missing? -joe t. On Jun 24, 12:20 pm, Rick Waldron waldron.r...@gmail.com wrote: I made a few modifications to your version, allowing repeat() to behave like delay() with regard to arguments I've posted a demo here: http://jsbin.com/ekone All the output is to the firebug console... i've included fbug lite just in case Rick On Wed, Jun 24, 2009 at 10:50 AM, Rick Waldron waldron.r...@gmail.comwrote: 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.comwrote: 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). 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); } // Start repeating this._repeatTimeout = setTimeout(this._repeater, delay); }, stopRepeating: function() { this.repeat(); } }); For example: 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. Object.extend(Function.prototype, { repeat: function() { var __method = this, args = $A(arguments), interval = args.shift() * 1000; return window.setInterval(function() { return __method.apply(__method, args); }, interval ); } }); // 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. Rick --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...]) -- Revised from Robert's version
Note this last revision brings back a bit more of Robert's version, it's more 50/50 now. Rick On Thu, Jun 25, 2009 at 12:53 PM, Rick Waldron waldron.r...@gmail.comwrote: You're right... It appears i copied the source in a bit hastily. After re-examining, I've revised again... http://jsbin.com/ajoqu Rick On Thu, Jun 25, 2009 at 9:37 AM, joe t. thooke...@gmail.com wrote: Rick, Maybe i'm missing how that revision works, but it appears to me that your stop property doesn't actually stop the repeater. Your stop returns before further execution happens, but the timeout ID for the window still exists. What am i missing? -joe t. On Jun 24, 12:20 pm, Rick Waldron waldron.r...@gmail.com wrote: I made a few modifications to your version, allowing repeat() to behave like delay() with regard to arguments I've posted a demo here: http://jsbin.com/ekone All the output is to the firebug console... i've included fbug lite just in case Rick On Wed, Jun 24, 2009 at 10:50 AM, 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.comwrote: 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). 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); } // Start repeating this._repeatTimeout = setTimeout(this._repeater, delay); }, stopRepeating: function() { this.repeat(); } }); For example: 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. Object.extend(Function.prototype, { repeat: function() { var __method = this, args = $A(arguments), interval = args.shift() * 1000; return window.setInterval(function() { return __method.apply(__method, args); }, interval ); } }); // usage: var _pollInt = 0; function repetiousPollFn() { console.log(_pollInt++); } repetiousPollFn.repeat(.5); Will, of
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...]) -- Revised from Robert's version
You're right... It appears i copied the source in a bit hastily. After re-examining, I've revised again... http://jsbin.com/ajoqu Rick On Thu, Jun 25, 2009 at 9:37 AM, joe t. thooke...@gmail.com wrote: Rick, Maybe i'm missing how that revision works, but it appears to me that your stop property doesn't actually stop the repeater. Your stop returns before further execution happens, but the timeout ID for the window still exists. What am i missing? -joe t. On Jun 24, 12:20 pm, Rick Waldron waldron.r...@gmail.com wrote: I made a few modifications to your version, allowing repeat() to behave like delay() with regard to arguments I've posted a demo here: http://jsbin.com/ekone All the output is to the firebug console... i've included fbug lite just in case Rick On Wed, Jun 24, 2009 at 10:50 AM, 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). 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); } // Start repeating this._repeatTimeout = setTimeout(this._repeater, delay); }, stopRepeating: function() { this.repeat(); } }); For example: 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. Object.extend(Function.prototype, { repeat: function() { var __method = this, args = $A(arguments), interval = args.shift() * 1000; return window.setInterval(function() { return __method.apply(__method, args); }, interval ); } }); // 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
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
Thanks for the insight Tobie, definitely appreciated. Function.prototype.repeat = function(interval) { return new PeriodicalExecuter(this, interval); } How to stop it? arguments? This may come to you twice, but this is slightly updated: http://jsbin.com/opimu 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.comwrote: Hi Rick, hi Robert. 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: 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). 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
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
You might also want to look at the already existing PeriodicalExecuter. Any implementation of a Function#repeat API should take this in account. On Jun 24, 2:55 pm, joe t. thooke...@gmail.com wrote: 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. Object.extend(Function.prototype, { repeat: function() { var __method = this, args = $A(arguments), interval = args.shift() * 1000; return window.setInterval(function() { return __method.apply(__method, args); }, interval ); } }); // 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. Rick --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
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); } // Start repeating this._repeatTimeout = setTimeout(this._repeater, delay); }, stopRepeating: function() { this.repeat(); } }); For example: 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. Object.extend(Function.prototype, { repeat: function() { var __method = this, args = $A(arguments), interval = args.shift() * 1000; return window.setInterval(function() { return __method.apply(__method, args); }, interval ); } }); // 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. Rick --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
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). 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); } // Start repeating this._repeatTimeout = setTimeout(this._repeater, delay); }, stopRepeating: function() { this.repeat(); } }); For example: 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. Object.extend(Function.prototype, { repeat: function() { var __method = this, args = $A(arguments), interval = args.shift() * 1000; return window.setInterval(function() { return __method.apply(__method, args); }, interval ); } }); // 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. Rick --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
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.comwrote: 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). 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); } // Start repeating this._repeatTimeout = setTimeout(this._repeater, delay); }, stopRepeating: function() { this.repeat(); } }); For example: 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. Object.extend(Function.prototype, { repeat: function() { var __method = this, args = $A(arguments), interval = args.shift() * 1000; return window.setInterval(function() { return __method.apply(__method, args); }, interval ); } }); // 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. Rick --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...]) -- Revised from Robert's version
I made a few modifications to your version, allowing repeat() to behave like delay() with regard to arguments I've posted a demo here: http://jsbin.com/ekone All the output is to the firebug console... i've included fbug lite just in case Rick On Wed, Jun 24, 2009 at 10:50 AM, Rick Waldron waldron.r...@gmail.comwrote: 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.comwrote: 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). 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); } // Start repeating this._repeatTimeout = setTimeout(this._repeater, delay); }, stopRepeating: function() { this.repeat(); } }); For example: 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. Object.extend(Function.prototype, { repeat: function() { var __method = this, args = $A(arguments), interval = args.shift() * 1000; return window.setInterval(function() { return __method.apply(__method, args); }, interval ); } }); // 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. Rick --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
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.comwrote: 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). 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); } // Start repeating this._repeatTimeout = setTimeout(this._repeater, delay); }, stopRepeating: function() { this.repeat(); } }); For example: 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. Object.extend(Function.prototype, { repeat: function() { var __method = this, args = $A(arguments), interval = args.shift() * 1000; return window.setInterval(function() { return __method.apply(__method, args); }, interval ); } }); // 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. Rick --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
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. :) Best, Tobie --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Prototype: Core group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to prototype-core-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
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.comwrote: 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). 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); } // Start repeating this._repeatTimeout = setTimeout(this._repeater, delay); }, stopRepeating: function() { this.repeat(); } }); For example: 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. Object.extend(Function.prototype, { repeat: function() { var __method = this, args = $A(arguments), interval = args.shift() * 1000; return window.setInterval(function() { return __method.apply(__method, args); }, interval ); } }); // usage: var _pollInt = 0; function repetiousPollFn() { console.log(_pollInt++); } repetiousPollFn.repeat(.5); Will, of course, repeat repetiousPollFn() every half second. Almost identical to
[Prototype-core] Re: Suggested addition to Function Methods: .repeat(seconds[, arg...])
Hi Rick, hi Robert. 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: 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.comwrote: 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). 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); } // Start repeating this._repeatTimeout = setTimeout(this._repeater, delay); }, stopRepeating: function() { this.repeat(); } }); For example: 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