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.
Results 1 to 13 of 13
  1. #1
    Regular Coder
    Join Date
    Feb 2003
    Posts
    638
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Recursive increment & setTimeout?

    Why does my function run out of memory if I don't use setTimeout(..., 0)?

    I can see what's happening:

    if the loop number is greater than 459, the error occurs, and without a timeout, the output moves at light-speed.

    However, I don't understand what's actually going on here...

    why does the "out of memory" error occur, and what does a zero timeout-delay do to correct the problem?

    Code:
    <html>
    <head>
    <title>-</title>
    
    <script type="text/JavaScript">
    
    var i, n, stop;
    
    function Recurse(oForm){
    i++;
    oForm.progress.value = i;
    oForm.percentage.value = Math.floor(((i / n) * 100)) + "%";
    i < n && +stop != 1 ? setTimeout(function (){Recurse(oForm);}, 0) : controlUpdate("Complete");
    }
    
    function controlUpdate(callString){
    oForm = document.RecTest;
    
    switch(callString){
    
    case "Start" : 
    n = new Number(oForm.test.value);
    if(isNaN(n) || n < 1){
    alert("loop value must be a number greater than 0. ");
    }
    else{
    i = 0;
    stop = false;
    oForm.cancel.disabled = 0;
    oForm.start.disabled = 1;
    oForm.test.disabled = 1;
    Recurse(oForm);
    }
    break;
    
    case "Cancel" : 
    stop = true;
    oForm.rs.disabled = 0;
    oForm.cancel.disabled = 1;
    break;
    
    case "Complete" : 
    oForm.rs.disabled = 0;
    break;
    
    case "Reset" : 
    oForm.cancel.disabled = 1;
    oForm.start.disabled = 0;
    oForm.test.disabled = 0;
    oForm.rs.disabled = 1;
    break;}
    }
    </script>
    
    <style type="text/css">
    form{
    text-align:center
    }
    input{
    text-align:center;vertical-align:middle
    }
    label{
    padding-left:10px;padding-right:5px
    }
    </style>
    
    </head>
    <body>
    
    <form name="RecTest" onreset="controlUpdate('Reset')">
    <label>i :</label><input name="progress" size="10" readonly>
    <label>% :</label><input name="percentage" size="10" readonly>
    <br><br>
    <label>loop :</label><input name="test" value="500" size="10" maxlength="5">
    <input name="start" type="button" value="Start" onclick="controlUpdate('Start')">
    <input name="cancel" type="button" value="Cancel" disabled onclick="controlUpdate('Cancel')">
    <input name="rs" type="reset" disabled>
    </form>
    
    </body>
    </html>
    Last edited by swmr; 02-09-2004 at 07:16 AM.
    hmm... ?

  • #2
    Supreme Master coder! glenngv's Avatar
    Join Date
    Jun 2002
    Location
    Philippines
    Posts
    11,068
    Thanks
    0
    Thanked 256 Times in 252 Posts
    liorean can explain this better but I might as well share that Javascript recursion has maximum depth. By using setTimeout or setInterval, you can make it an endless loop.
    Glenn
    ____________________________________

    My Blog
    Tower of Hanoi Android app (FREE!)
    Tower of Hanoi Leaderboard
    Samegame Facebook App
    vBulletin Plugins
    ____________________________________

  • #3
    Regular Coder
    Join Date
    Feb 2003
    Posts
    638
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Yeah, that's interesting... I wonder what the difference is between maximum depth, or memory (or whatever), as it applies to the Function Object vs. the For/While Statements... and, why those statements won't show output results until they have finished looping.
    hmm... ?

  • #4
    New to the CF scene
    Join Date
    Feb 2004
    Posts
    1
    Thanks
    0
    Thanked 0 Times in 0 Posts
    hi,
    what the javascript interpreter does if it detects true recursivnes, like you use it here, is pushing the function object on the execution stack each time it gets called.
    this is why the memory usage rises so rapidly and it stops when the interpreter needs more memory then it reserves itself. thats why the results vary for different browsers because there is no definition how much memory a javascript interpreter should use and each browser handles this differently.
    in some languages there is a technique called "tail call elimination", where the interpreter detects and removes unmodified objects from the stack, so that you can recurse endlessly but this is not covered in the ecma-scriüt spec and there exists only one javascript interpreter which can handle this (http://wiki.cocoondev.org/Wiki.jsp?p...hContinuations).
    so as long as you don't know how often you have to recurse or supply a mechanism to break out of the recursion, usage setTimeout() or
    setInterval() is better as it uses always the same function object but with the defined delay between the calls.

  • #5
    Regular Coder
    Join Date
    Feb 2003
    Posts
    638
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thank you for explaining that.
    hmm... ?

  • #6
    Master Coder
    Join Date
    Feb 2003
    Location
    Umeå, Sweden
    Posts
    5,575
    Thanks
    0
    Thanked 83 Times in 74 Posts
    There is one thing to it, though: A recursive function returns the results to the context. A function called from a setTimeout or setInterval doesn't. That may or may not limit the possibility of using setTimeout or setInterval for this kind of job. In general an iterative statement such as the do..while loop, the while loop or the for loop is the better choice.
    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

  • #7
    Regular Coder
    Join Date
    Feb 2003
    Posts
    638
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Thanks liorean, would you happen to have any code snippets that illustrate the difference there?

    From what I gather, recursion is the only way to update a control - such as a progress bar - for each incremental step... so it seems that's where it would be required.
    hmm... ?

  • #8
    Supreme Master coder! glenngv's Avatar
    Join Date
    Jun 2002
    Location
    Philippines
    Posts
    11,068
    Thanks
    0
    Thanked 256 Times in 252 Posts
    FWIW...
    Code:
    <html>
    <head>
    <title>-</title>
    
    <script type="text/JavaScript">
    
    var i, n, stop, timer;
    
    function Recurse(oForm){
    i++;
    oForm.progress.value = i;
    oForm.percentage.value = Math.floor(((i / n) * 100)) + "%";
    if (i >= n || stop) controlUpdate("Complete");
    }
    
    function controlUpdate(callString){
    oForm = document.RecTest;
    
    switch(callString){
    
    case "Start" : 
    n = new Number(oForm.test.value);
    if(isNaN(n) || n < 1){
    alert("loop value must be a number greater than 0. ");
    }
    else{
    i = 0;
    stop = false;
    oForm.cancel.disabled = 0;
    oForm.start.disabled = 1;
    oForm.test.disabled = 1;
    timer = setInterval(function(){Recurse(oForm)},1);
    }
    break;
    
    case "Cancel" : 
    clearInterval(timer);
    stop = true;
    oForm.rs.disabled = 0;
    oForm.cancel.disabled = 1;
    break;
    
    case "Complete" : 
    clearInterval(timer);
    oForm.rs.disabled = 0;
    break;
    
    case "Reset" : 
    oForm.cancel.disabled = 1;
    oForm.start.disabled = 0;
    oForm.test.disabled = 0;
    oForm.rs.disabled = 1;
    break;}
    }
    </script>
    
    <style type="text/css">
    form{
    text-align:center
    }
    input{
    text-align:center;vertical-align:middle
    }
    label{
    padding-left:10px;padding-right:5px
    }
    </style>
    
    </head>
    <body>
    
    <form name="RecTest" onreset="controlUpdate('Reset')">
    <label>i :</label><input name="progress" size="10" readonly>
    <label>% :</label><input name="percentage" size="10" readonly>
    <br><br>
    <label>loop :</label><input name="test" value="500" size="10" maxlength="5">
    <input name="start" type="button" value="Start" onclick="controlUpdate('Start')">
    <input name="cancel" type="button" value="Cancel" disabled onclick="controlUpdate('Cancel')">
    <input name="rs" type="reset" disabled>
    </form>
    
    </body>
    </html>
    Last edited by glenngv; 02-10-2004 at 02:38 AM.
    Glenn
    ____________________________________

    My Blog
    Tower of Hanoi Android app (FREE!)
    Tower of Hanoi Leaderboard
    Samegame Facebook App
    vBulletin Plugins
    ____________________________________

  • #9
    Regular Coder
    Join Date
    Feb 2003
    Posts
    638
    Thanks
    0
    Thanked 0 Times in 0 Posts
    stop = false; if(!stop)... -- that's good to know!


    Thanks for the example, glenngv.

    Is there an advantage to using setInterval instead of setTimeout, here, or was that just to demonstrate the alternative?
    hmm... ?

  • #10
    Supreme Master coder! glenngv's Avatar
    Join Date
    Jun 2002
    Location
    Philippines
    Posts
    11,068
    Thanks
    0
    Thanked 256 Times in 252 Posts
    If you want to call the function repetitively, then setInterval is better because you don't have to call the function again inside that function. But if you want to call the function only once with a delay, then use setTimeout.
    Glenn
    ____________________________________

    My Blog
    Tower of Hanoi Android app (FREE!)
    Tower of Hanoi Leaderboard
    Samegame Facebook App
    vBulletin Plugins
    ____________________________________

  • #11
    Regular Coder
    Join Date
    Feb 2003
    Posts
    638
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Ah, setInterval does sound more appropriate, but how can I know how long a function will take to execute: would there be a possibility of calling it again too soon?

    Also, what happens differently when a function is called from within itself?
    hmm... ?

  • #12
    Supreme Master coder! glenngv's Avatar
    Join Date
    Jun 2002
    Location
    Philippines
    Posts
    11,068
    Thanks
    0
    Thanked 256 Times in 252 Posts
    setInterval will wait for the function to finish execution before executing the function again unless there is setTimeout inside in which the setInterval function is re-executed regardless the setTimeout function has finished execution or not. Hope that makes sense.

    According to this test, setTimeout is faster than setInterval.
    Glenn
    ____________________________________

    My Blog
    Tower of Hanoi Android app (FREE!)
    Tower of Hanoi Leaderboard
    Samegame Facebook App
    vBulletin Plugins
    ____________________________________

  • #13
    Regular Coder
    Join Date
    Feb 2003
    Posts
    638
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Yeah, that made sense; thank you.
    hmm... ?


  •  

    Posting Permissions

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