Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Page 1 of 2 12 LastLast
Results 1 to 15 of 28
  1. #1
    Regular Coder
    Join Date
    Jul 2002
    Location
    USA
    Posts
    151
    Thanks
    0
    Thanked 0 Times in 0 Posts

    The Timer class, for object-oriented timeouts

    The problems with the setTimeout and setInterval functions provided in Javascript are twofold. First, you can't call a local object method without losing your scope, and second, you can't pass objects to the function, since the function call is implemented as a string.

    The Timer class solves these difficulties by employing a static array to store the parent object and function arguments until the function is called.

    This class is provided as-is and pro bono, so go ahead and muck with it if you see things that could be done better.

    Thanks to WA for giving me the idea for this (albeit indirectly)!

    Updated 4/18/2003: Footprint decreased, minor code improvements.
    Updated 5/3/2003: Minor comment clarification; no code changes.
    Updated 5/10/2003: Minor code improvements.
    Code:
    // The constructor should be called with
    // the parent object (optional, defaults to window).
    
    function Timer(){
        this.obj = (arguments.length)?arguments[0]:window;
        return this;
    }
    
    // The set functions should be called with:
    // - The name of the object method (as a string) (required)
    // - The millisecond delay (required)
    // - Any number of extra arguments, which will all be
    //   passed to the method when it is evaluated.
    
    Timer.prototype.setInterval = function(func, msec){
        var i = Timer.getNew();
        var t = Timer.buildCall(this.obj, i, arguments);
        Timer.set[i].timer = window.setInterval(t,msec);
        return i;
    }
    Timer.prototype.setTimeout = function(func, msec){
        var i = Timer.getNew();
        Timer.buildCall(this.obj, i, arguments);
        Timer.set[i].timer = window.setTimeout("Timer.callOnce("+i+");",msec);
        return i;
    }
    
    // The clear functions should be called with
    // the return value from the equivalent set function.
    
    Timer.prototype.clearInterval = function(i){
        if(!Timer.set[i]) return;
        window.clearInterval(Timer.set[i].timer);
        Timer.set[i] = null;
    }
    Timer.prototype.clearTimeout = function(i){
        if(!Timer.set[i]) return;
        window.clearTimeout(Timer.set[i].timer);
        Timer.set[i] = null;
    }
    
    // Private data
    
    Timer.set = new Array();
    Timer.buildCall = function(obj, i, args){
        var t = "";
        Timer.set[i] = new Array();
        if(obj != window){
            Timer.set[i].obj = obj;
            t = "Timer.set["+i+"].obj.";
        }
        t += args[0]+"(";
        if(args.length > 2){
            Timer.set[i][0] = args[2];
            t += "Timer.set["+i+"][0]";
            for(var j=1; (j+2)<args.length; j++){
                Timer.set[i][j] = args[j+2];
                t += ", Timer.set["+i+"]["+j+"]";
        }}
        t += ");";
        Timer.set[i].call = t;
        return t;
    }
    Timer.callOnce = function(i){
        if(!Timer.set[i]) return;
        eval(Timer.set[i].call);
        Timer.set[i] = null;
    }
    Timer.getNew = function(){
        var i = 0;
        while(Timer.set[i]) i++;
        return i;
    }
    Here's an example of the code in action:
    Code:
    function Ticker(){
        this.count = 0;
        this.timer = new Timer(this);
    }
    Ticker.prototype.tick = function(d){
        this.count+=d;
        window.status = ""+this.count;
        this.timer.setTimeout("tick", 1000, d);
    }
                       
    window.onload = function(){
        var ticker = new Ticker();
        ticker.tick(1);
    }
    Last edited by Algorithm; 05-10-2003 at 11:38 AM.

  • #2
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Hey Algorithm

    I don't know if anyone else here uses this, but I've implemented it into a couple scripts I'm working on that are OO in nature. I wouldn't be able to do them without a OO-based timeout include, and this one works wonderfully.

    Thanks for the great code!
    My Site | fValidate | My Brainbench | MSDN | Gecko | xBrowser DOM | PHP | Ars | PVP
    “Minds are like parachutes. They don't work unless they are open”
    “Maturity is simply knowing when to not be immature”

  • #3
    Regular Coder Skyzyx's Avatar
    Join Date
    Aug 2002
    Location
    Silicon Valley, CA
    Posts
    980
    Thanks
    0
    Thanked 0 Times in 0 Posts
    BTW, you CAN pass variables to setTimeout() and setInterval().

    Code:
    setTimeout('myFunction()', 1000, parameter1, parameter2, ..., parameter[n]);
    But your code is still cool!

    Creator of SimplePie and Tarzan AWS, co-founder of WarpShare, co-built the Y! Messenger website, usability-focused, and an INFJ personality.

  • #4
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Skyzyx. I've never seen that, and neither of these pages indicate that.

    Have you actually used this?
    My Site | fValidate | My Brainbench | MSDN | Gecko | xBrowser DOM | PHP | Ars | PVP
    “Minds are like parachutes. They don't work unless they are open”
    “Maturity is simply knowing when to not be immature”

  • #5
    Senior Coder
    Join Date
    Jun 2002
    Location
    Wichita
    Posts
    3,880
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Originally posted by Skyzyx
    BTW, you CAN pass variables to setTimeout() and setInterval().

    Code:
    setTimeout('myFunction()', 1000, parameter1, parameter2, ..., parameter[n]);
    But your code is still cool!
    Sorry but that's a Netscape extension and it's not supported in IE. I may only be supported in Netscape 4, don't know if later versions of Netscape support it or not.

  • #6
    Senior Coder
    Join Date
    Jun 2002
    Location
    near Oswestry
    Posts
    4,508
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: The Timer class, for object-oriented timeouts

    Originally posted by Algorithm
    you can't pass objects to the function, since the function call is implemented as a string.
    Yeah you can - I do this all the time:
    Code:
    var tempObj1,tempObj2,theTimer;
    function someFunction(obj1,obj2)
    {
        tempObj1 = obj1;
        tempObj2 = obj2;
        theTimer = setInterval("someFunction(tempObj1,tempObj2)",100);
    }
    It may be passed as a string, but it still evaluates as an object reference.
    "Why bother with accessibility? ... Because deep down you know that the web is attractive to people who aren't exactly like you." - Joe Clark

  • #7
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts
    I think we've been talking about passing local variables, brothercake, at least I know I have. I mean, if you're using global variables there's no point in passing them at all
    My Site | fValidate | My Brainbench | MSDN | Gecko | xBrowser DOM | PHP | Ars | PVP
    “Minds are like parachutes. They don't work unless they are open”
    “Maturity is simply knowing when to not be immature”

  • #8
    Master Coder
    Join Date
    Feb 2003
    Location
    Umeå, Sweden
    Posts
    5,575
    Thanks
    0
    Thanked 83 Times in 74 Posts
    Didn't Alex post a nice and small way to do this some time ago? (Like when I last frequented this forum, before the change of name from WSAbstract to JS Kit...)
    liorean <[lio@wg]>
    Articles: RegEx evolt wsabstract , Named Arguments
    Useful Threads: JavaScript Docs & Refs, FAQ - HTML & CSS Docs, FAQ - XML Doc & Refs
    Moz: JavaScript DOM Interfaces MSDN: JScript DHTML KDE: KJS KHTML Opera: Standards

  • #9
    Regular Coder
    Join Date
    Jul 2002
    Location
    USA
    Posts
    151
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thanks for the great feedback, guys, and thanks especially to beetle for his heavy promotion of the class.

    I've updated the code to remove the global array and decrease the class's footprint by half, as well as to make minor improvements throughout the class. The code should run cleaner now and with less unnecessary delay.

    Any feedback on this new version would be more than appreciated.

  • #10
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Great! I'll d/l it right away.

    No implementation changes, right? :P

    Greak work
    My Site | fValidate | My Brainbench | MSDN | Gecko | xBrowser DOM | PHP | Ars | PVP
    “Minds are like parachutes. They don't work unless they are open”
    “Maturity is simply knowing when to not be immature”

  • #11
    New to the CF scene
    Join Date
    Apr 2003
    Location
    London
    Posts
    4
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Nice class.

    Shame you are using strings on the setTimeout instead of passing a function reference.

    Any syntax errors would not be clear to the developer as the string is evaluated at runtime. The code is ugly and there is simply no need for this uglyness. Simple scope guys..

    We have commented on the script @ DC:

    http://www.dhtmlcentral.com/forums/t...TOPIC_ID=17585

  • #12
    Regular Coder
    Join Date
    Jul 2002
    Location
    USA
    Posts
    151
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Originally posted by Tim Scarfe
    Shame you are using strings on the setTimeout instead of passing a function reference.

    Any syntax errors would not be clear to the developer as the string is evaluated at runtime. The code is ugly and there is simply no need for this uglyness. Simple scope guys..
    The problem is, there's numerous pitfalls involved in attempting to use a function reference. Passing it directly to window.setTimeout would nullify the scope (not to mention making the code inoperable in several browsers). Storing the reference for the duration would necessitate appending a temporary value to the parent object, and -- if at all possible -- altering external objects is something I emphatically want to avoid. The only other option would be to pass the method name along with the reference, which I consider redundant.

    I agree that, if it were workable, passing a reference would be preferable to passing the name; however, I see no method in which it would work without alienating browsers or altering external objects. Feel free to prove me wrong.

  • #13
    New to the CF scene
    Join Date
    Apr 2003
    Location
    London
    Posts
    4
    Thanks
    0
    Thanked 0 Times in 0 Posts
    The problem is, there's numerous pitfalls involved in attempting to use a function reference. Passing it directly to window.setTimeout would nullify the scope (not to mention making the code inoperable in several browsers). Storing the reference for the duration would necessitate appending a temporary value to the parent object, and -- if at all possible -- altering external objects is something I emphatically want to avoid. The only other option would be to pass the method name along with the reference, which I consider redundant.
    Sorry, No. This is just wrong wrong wrong, and doesn't entirely make sense. Apart from this bit:

    (not to mention making the code inoperable in several browsers).
    *Scope is not lost
    *You don't need to make any objects or properties or whatever you were saying
    *Performance is greater with functions
    *You want object instance code running in global scope, duh?
    *You want to discover syntax errors at runtime?
    *You want ugly code in strings? i.e. clearer code
    *code is more encapsulated
    *more clever things like applying functions possible

    What you have done is just like using eval(), and we all know eval is evil, or you SHOULD.

    As I said on DC, IE5.00 and some really ancient browsers have problems with this, but it's really a no brainer argument as proper scope is used in all properly written DHTML classes.

    I'm way too tired to proove this now and I need sleep, but I have flagged this up on my to-do list for tommorrow, and it's a high priority! I've done well to post this much after the crazy night I've just returned from

    In the mean time, I will quote Erik Advisson of webfx.eae.net fame:

    // 27/05/2002 14:14

    How come people keep using eval and the setTimeout eval counterpart. JS is a language that supports higher order functions and thus the best way to use setTimeout is to use the version that uses this feature. Compare the following two cases and decide for yourself which one to prefer.

    // alt. 1
    // non global code
    var obj = getSomeObject();
    makeObjectGloballyAccessible(obj); // in your case you put it in a global array
    window.setTimeout(getGlobalAccessCode(obj) + ".someMethod()", t);

    // alt. 2
    // non global code
    var obj = getSomeObject();
    window.setTimeout(function() { obj.someMethod(); }, t);

    The second one does not require any global references to objects and it allows you to use write code instead of strings. There are quite a few reasons to use alt. 2:

    * Allows anonymous code, i.e. non-global objects
    * Garbage collection can correctly dispose objects because there are no global references
    * Easier to write
    * Syntax errors are caught at startup.
    * No eval. Evals are slow and error prone. Eval happen at runtime and cannot be compiled/checked. Even in a non compiled environment these are significantly slower than non-evaluated code.
    * No need for code that makes object available as globals and no need for code to reference the global object

    There is one downside to using the higher order function version of setTimeout and that is that it does not work in Netscape 3, IE3 (4?) and crashes IE5.0 (without any fixes, 5.01 works fine). But then again, targeting IE5.0 and NN4 and any of the old, non-dom browsers is not the choice of a true visionary :-)

    erik

  • #14
    Senior Coder
    Join Date
    Aug 2002
    Posts
    3,467
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Great arguments et points Tim - but I think you could step off the pedastal a bit (and Eric too)

    Ignoring the fact that most people writing javascript aren't programmers is a bit pious. The fact of the matter is, many people (20%+) still use IE5 -- whether 5.0 or 5.01 I do not know, but when working for a client and not oneself, we have to keep these things in mind regardless of our capacity to be a "visionary".

    This is great information to have and I thank you for that - I just think you could have presented your case with a bit more tact.

    I don't think any more explanation is needed -- anyone that can grasp what scope is and understands OO js should have no trouble seeing what's going on in your last post.

    Oh, and welcome to codingforums.com
    Last edited by beetle; 05-10-2003 at 06:23 AM.
    My Site | fValidate | My Brainbench | MSDN | Gecko | xBrowser DOM | PHP | Ars | PVP
    “Minds are like parachutes. They don't work unless they are open”
    “Maturity is simply knowing when to not be immature”

  • #15
    WA
    WA is offline
    Administrator
    Join Date
    Mar 2002
    Posts
    2,596
    Thanks
    2
    Thanked 19 Times in 18 Posts
    Hi Tim:
    Thanks for the info- it's certainly useful, and we do appreciate it. Personally though, the fact that this technique doesn't work in IE5 means I wouldn't even consider using it for now, since as someone mentioned, usability to me is just as important as elegance, if not more so.

    Again, it's great information, though I may need to go back and study it some more to even get it.
    - George
    - JavaScript Kit- JavaScript tutorials and 400+ scripts!
    - JavaScript Reference- JavaScript reference you can relate to.


  •  
    Page 1 of 2 12 LastLast

    LinkBacks (?)

    1. 07-14-2014, 10:18 AM
    2. 02-24-2014, 03:49 AM

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •