How to create anl infinite loop in JavaScript - Beginner Tip

Discussion in 'Scripts, 3rd Party Apps, and Programming' started by anonychair38, Nov 29, 2011.

  1. anonychair38

    anonychair38 New Member

    Messages:
    8
    Likes Received:
    0
    Trophy Points:
    0
    JavaScript is a memory hog. Most programmers know this. What a lot of new programmers do not know, is that you cannot create an infinite loop in JavaScript using While/For loops or other conditional statements. Theoretically, it is possible. But, the browser has a way of detecting this. Say for example, my code was:

    Code:
    ten = 1
    while (ten = 1) {
     //some code here
    }
    
    Since I declared the variable ten as 1, the while condition will always be true. Therefore, it will loop forever. BUT, after a few minutes of looping, the browser will halt the loop, and open a dialogue box. This dialogue box will say something along the lines of "Excessive memory usage. JavaScript on page still running. Continue?" and then prompt the user to either click yes or no. Should the user click no, the JavaScript will stop looping.

    Fortunately, there is a way to work around this dialogue using setTimeout, and a recursive function.

    What is a recursive function?
    Normally, when a function is defined by the programmer, it is so the function can be used elsewhere in the code. A recursive function differs because the function name is called within the function itself. When we combine this with setTimeout, it creates an infinite loop that repeats itself according to the time you set in setTimeout.

    So, to execute code every 5 seconds in an infinite loop, our code will be:

    Code:
    
    [COLOR=#003366][B]function[/B][/COLOR] loop[COLOR=#009900]([/COLOR][COLOR=#009900])[/COLOR] [COLOR=#009900]{[/COLOR]        [COLOR=#006600][I]// your code[/I][/COLOR]         setTimeout[COLOR=#009900]([/COLOR][COLOR=#3366CC]"loop()"[/COLOR][COLOR=#339933],[/COLOR] [COLOR=#CC0000]5000[/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR] 	[COLOR=#006600][I]// 5000 milliseconds = 5 seconds[/I][/COLOR]    [COLOR=#009900]}[/COLOR]    loop[COLOR=#009900]([/COLOR][COLOR=#009900])[/COLOR][COLOR=#339933];[/COLOR]
    As you can see, I have created a function called loop(). I have then called this function within setTimeout, which is already inside the function.

    Knowing this is useful if you want to create a slideshow that scrolls through each image and then repeats the process.

    Just a tip for beginner programmers.
     
  2. misson

    misson Community Paragon Community Support

    Messages:
    2,572
    Likes Received:
    72
    Trophy Points:
    48
    The problem with an infinite loop isn't memory usage, it's processor usage.

    Using setTimeout that way doesn't give you an infinite loop, per se. Infinite loops are a subject for computational models that require termination for a program to be correct; a program with an infinite loop will never terminate. setTimeout doesn't guarantee the function will run forever, merely that it will run while the program runs. The program can still terminate. Moreover, the computational model behind repeated execution doesn't require termination for a program to be correct. In simpler terms, an infinite loop causes the program to hang; scheduling a function to run repeatedly does not.

    If you want to run a function periodically, setInterval is what you should use.
     
  3. essellar

    essellar Community Advocate Community Support

    Messages:
    3,295
    Likes Received:
    227
    Trophy Points:
    63
    By the way, your example doesn't test the value of the variable ten; it tests whether the variable ten[c] can be assigned a value of [c]1. That's why this construct:

    Code:
    if (variable == 1) {...}
    
    is strongly discouraged in favour of the Yoda version:

    Code:
    if (1 == variable) {...}
    
    When you accidentally use the assignment operator (=) instead of the equivalency test (==) or the equality/identity test (===), you get an error (a compiler error in a compiled language or a runtime error in an interpreted language) because you can't assign a value to a literal.
     
  4. anonychair38

    anonychair38 New Member

    Messages:
    8
    Likes Received:
    0
    Trophy Points:
    0
    @esselar, My example was a form of pseudocode, just to get the general idea across. It's still understandable and makes the point. Remember, this is a beginner tip.

    @misson, While it isn't an infinite loop, it still runs forever. I've used it without error, though it might be considered better to use setInterval, this is not the case within a recursive function. setInterval will run the loop infinitely without any further prompting, so every time loop() is called, another timer thread is started which will run loop(), which will spawn thread after thread after thread, which is why setTimeout() should be used.
     
    Last edited: Nov 29, 2011
  5. misson

    misson Community Paragon Community Support

    Messages:
    2,572
    Likes Received:
    72
    Trophy Points:
    48
    It doesn't read as pseudocode. It's not labeled as such, it's valid JS and it's in a post about JS. Hence, it reads as JS. On the other hand, if it's not taken as JS and "=" means assignment in one context and equality comparison in another, it's even worse because it's ambiguous (hence, confusing), not simply a typo.

    The example makes more than one point, one of which is wrong.

    All the more reason to use the proper operator. Beginners won't likely be aware of the issue of using assignment when equality comparison is called for. As a result, they'll be confused and may develop misunderstandings. Thus it's not as understandable as you think.

    Example code tends to be copied verbatim by novice programmers, even the parts that shouldn't, which is why great care must be taken when writing examples. If necessary, point out what part of an example shouldn't be used in production code (which is what essellar did). Joshua Block makes this point in his excellently informative lecture "How to Design a Good
    API and Why it Matters
    ". He uses this in the context of code examples for APIs, but it holds for all code examples.

    Programming is a subtle discipline. Though the loop function runs forever, there's an important difference between a non-terminating program and an infinite loop. An infinite loop is a bug; a correct program won't have an infinite loop. Infinite loops are something to be done away with; they don't have alternatives. As a consequence, neither setTimeout nor setInterval is an alternative for an infinite loop.

    Just because something doesn't produce an error doesn't mean it's the right approach. Take essellar's example. Using ten == 1 doesn't cause an error, but it's more susceptible to typos and bugs. With 1 == ten, the interpreter (or compiler) will inform you that there's an error in the code, letting you catch it earlier and easier. Another useful convention is to surround assignment within conditions with an extra set of parentheses as a sign that the assignment is on purpose:

    Code:
    // the extra parentheses mean the assignment is intentional
    if ((foo = 42)) {
        ...
    }
    
    // is the assignment intentional, or is it a typo?
    if (foo = 42) {
        ...
    }
    
    Many other conventions and practices are the same: there are best practices, which ease development, and bad practices, which have pitfalls. Development is more than programming; what's fine from a programming perspective (that is, something that isn't incorrect) may not be acceptable from a development perspective.

    Your loop function isn't strictly a recursive function. It never calls itself, even indirectly via another function (mutual recursion). Rather, it queues a task that will call the function after a delay. It's closer to iteration if anything (you don't see the loop since it's internal to the host environment), though an event model provides a better description than that. Of course, recursion and iteration are equivalent, but that's far beyond beginner level.

    The JS engine in most (all?) browsers is single-threaded. Even if it weren't, neither setTimeout nor setInterval would spawn a new thread. Instead, they schedule a task in a task queue so that the task will be executed later by the event loop.

    Additionally, what you describe wouldn't happen when setTimeout is properly replaced with setInterval. The latter wouldn't be called it every time the function is called; instead, it's called only once to start the process:

    Code:
    function loop() {
        ...
    }
    (function () {
        var loopIval;
        window.startLoop = function (delay) {
            // ensure loop is started at most once.
            if (! loopIval) {
                loop();
                loopIval = setInterval(loop, delay);
            }
        };
    })();
    
    If loop should never be called by outside code (i.e. only run within the task queue), then it should be moved to inside the anonymous function where startLoop is called.

    Note that in this example, the delayed function call is passed as a function rather than a string. Using strings is considered bad form. It works fine for nullary (zero argument) functions, but leads to complications when trying to pass arguments.

    The only time repeated execution using setTimeout can't properly be replaced with setInterval is when the delay isn't periodic.


    Some of this may seem trivial to you, but I assure you that it's not. On occasion, a beginner may not be ready for an idea and will require an intermediate idea that is wrong in certain ways in order to make progress, but that's not the case here. There's no more difficult concept hiding behind setTimeout and setInterval. It's harder to unlearn a bad concept than it is to learn a new concept.
     
  6. anonychair38

    anonychair38 New Member

    Messages:
    8
    Likes Received:
    0
    Trophy Points:
    0
    Are you telling me the information I learned while obtaining my degree in information systems internet development is wrong? First of all, the pseudocode is valid. I've been programming for years and trust me - using setInterval is a threaded monster learned both from experience and education.
     
  7. misson

    misson Community Paragon Community Support

    Messages:
    2,572
    Likes Received:
    72
    Trophy Points:
    48
    Which information, specifically?

    I, to, have a degree and a decade of experience in web development.

    I never stated the pseudocode was invalid. I wrote that it doesn't read as pseudocode and that, if taken as pseudocode, it's confusing.

    Here, I would question your experience and education. Professors can be victims of misinformation, same as anyone else. Do you have evidence that setInterval causes threading-related issues?

    Let's start with John Resig's (whose credentials, I hope, are not in doubt) post on Javascript timers:
    It goes on to illustrate how tasks are handled in a single thread and brings up another point that should be made: both setTimeout and setInterval are best-effort. The delay for setTimeout may be longer than requested. Similarly, a task created by setInterval may run later than scheduled, causing the actual execution intervals to be longer then shorter than the requested interval duration. For delay precision in animations (anything that changes the display of the webpage), the animation timing API should be used. For other uses, the design should account for extended delays (which, in some cases, may very well mean using setTimeout over setInterval; however, this depends on the exact use-case).

    Yet another important difference between the two is the same function is executed every time with setInterval, while different arguments can be passed to the function (indeed, a different function can even be used) executed via setTimeout. (This goes against my earlier statement that there was only one case where setInterval couldn't replace setTimeout, which I admit now was an overstatement.)

    Neither setInterval nor setTimeout is applicable for all repeated execution needs. Which should be used comes down to the specific requirements of the problem that the repeated execution is supposed to solve. Your original example passes no arguments an executes the function "every 5 seconds" (as opposed to "with 5 seconds between each execution"), so setInterval is the better match.
     

Share This Page