How does the browser handle infinite loop in Javascript?

Asked

Viewed 2,738 times

11

I was doing an exercise on loop repetition for in Javascript on Codecademy, however, in the exercise I came across the following warning:

codecadeny

Be very careful with your syntax - if you write a loop that does not can finish correctly, it is called infinite loop and will crash your browser!

And there I went to test:

for (var i = 2; i > 0; i++) {
	console.log(i);
}

The responsibility to execute the above code is yours, it serves only as an example.

And guess what happened? Imagem ilustrativa

That’s what stopped it all :D

However, this situation has left me with some doubts that are:

  1. How the browser handles the infinite loop?
  2. Why the locking occurs?
  3. In the WEB development environment there is some form or tool that minimizes the effects caused by the infinite loop?
  • If you have any improvement suggestions you can leave a comment.

  • 5

    I think it deals by breaking the infractive tab :D How it detects I don’t know, if it does. In general browsers have a tool that allows giving pause/put a breakpoint on the run, after all JS runs on a VM, with plenty of control if you’re in developer mode.

  • I’m learning WEB programming and this effect is more devastating than in Desktop kkkk, I think it doesn’t even detect, maybe some IDE alerts about it, but I don’t know.

  • maybe it’s of interest : How to release frozen/locked thread?

  • 3

    Here I did not leave long, but although the page stay stuck, just close on the X tab that is fine. The cool thing is that Opera 12 handles it better (I tested it now to be sure) than the current version, which uses the same engine as Chrome. The current hangs. In 12 gets a little slow the browser, but everything works. I even scroll on the page with loop running, open console, etc., which basically indicates this as an answer: it only depends on the implementation of each browser.

3 answers

13


There are several different scenarios that can crash your browser - not to mention the bugs. :P

Lengthy execution

To time consuming execution of a script can make it get blocked, but not necessarily cause a lock.

Example:

for (var i = 2; i > 0; i++) {}

The above code does not cause the page to lock or occupy the processor, but since the execution of Javascript in the browser is performed synchronously, this means that the browser is prevented from performing other actions on that page.

If the browser has some protection against this, it will identify that the script is taking too long to return (timeout) and offer an option to the user to "kill" the process of that page or tab. Otherwise you will have to terminate the browser as an all.

Memory consumption

However, the sample question code is not only locked in an infinite loop, but also generates an infinite amount of output to the console.

Unless you have disabled the console, the data will be stored somewhere in the memory until there is no more space available and then you will have a failure in the process. If the console is being displayed in the Developer Tool, this is even worse because the browser has to update the user interface, performing various calculations of positioning of the texts, among other things.

Browsers can use different techniques to prevent a full crash, such as Chrome, which uses a process per page or tab, which means that if a tab crashes, just "kill" and the consumed memory will be recovered without prejudice to the system and other pages or tabs.

Note that this is just one of many ways to consume a lot of memory. For example:

  • Memory leaks can be introduced by indefinitely adding values to objects or lists, or maintaining references to elements that are not even on the page.
  • Working with very large strings, concatenating loops and similar things can also kill memory.
  • Using recursiveness without a proper limit will also lock the script.

Avoiding such problems

The truth is that there is no practical and safe way to avoid this kind of problem because there are many different constructions in language that can lead to such situations.

However, the best approaches I know are:

  1. Write modular code (AMD, SE6) where functions and variables are isolated as much as possible.
  2. Test your code in an automated and unitary way (Qunit, Jasmine).
  3. Use tools of linting (Eslint), that is, that they analyze their code statically, according to pre-established rules, looking for bad practices and possible misunderstandings.
  4. Use the functional paradigm when possible

Specifically on item #3, Eslint has a list of rules defined among which there are some that can detect loops without stopping conditions, such as this. If there are any frequent mistakes that are not there, you can write your own rule.

Why modular code

Something important is that the more confused your code, the less effective the tests and static analysis. That’s why item #1 on my list above is in this position.

For example, many people use global scope variables in bonds. The behavior of this type of code is absurdly complex to predict.

function f1() {
    for (i = 0; i < 10; i++) f2(); 
}
function f2() {
    for (i = 0; i < 5; i++) whatever(); 
}

In the above example, f1 flame f2 for each execution of the loop. However i is not a local variable, so f2 will always end with i = 5 and the tie in f1 will never end.

Why functional paradigm

The Brunorb mentioned something very important above, which is the use of routines like forEach instead of manually doing the loop.

The functional programming paradigm is known to avoid several inherent problems of the imperative paradigm, such as this case.

The idea is to use special routines that encapsulate the logic of traversing a given data structure, after all they are implemented once, tested and have very little chance of suffering regressions. From diss you can perform actions on each element of the data structure using a function callback.

It is only important to consider that although this helps not to err with the counter of a loop, it still does not fully protect against misuse of global variables or that are shared with other functions, as in the example above.

6

As 1 and 2 have already been well answered in the comments of the question and in Sergio’s response I’ll just give you an additional on 3: It’s interesting to understand how detecting an infinite loop is an intractable problem called Halting Problem, both for the browser and for some static code analysis tool it is impossible to detect infinite loops (except in cases such as while(true);, which is not very useful), the best that the browser can do is check that your code is running too long without pause which indicates that something is wrong, and then it can make a decision about what to do, but this will vary depending on what the one who implemented thinks is the best.

About ways to avoid infinite ties there are certain code practices that make it impossible for them to occur, an example is that if instead of using a for(;;) traditional you always iterate on arrays with forEach or for...in, or in objects with for...in (forEach only works in arrays), it is impossible to iterate infinitely. For cases where you do not want to iterate over an object or array, but rather run certain "N" chunk times an option is to create an array with the size equal to the number of iterations you want to do and use it in conjunction with a foreach, example:

// obs, fill só existe em chrome >=45 e firefox >=31
new Array(10).fill().forEach(function() {
   console.log('olá');
});

It’s kind of exotic, mainly because javascript doesn’t have a clean way to create an X-size array, performance will also suffer (although you need to create a really large amount of reasonably sized loops to make it relevant)but it’s a cool technique to get to know (also because it’s the default way to iterate in python and ruby and is as clean as a default in php).

5

How the browser handles the infinite loop?

He crashes. Believes the developer knows what he’s doing and runs the code blindly, blocking.

Why the locking occurs?

Because it uses maximum execution capacity. The example you have in the question does not give the browser room to breathe, it will try to run it as fast as possible, infinite times. And how Javascript processing is single threaded it just runs that process and the rest of the code waits for the loop to end. It never happens.

In the WEB development environment there is some form or tool that minimizes the effects caused by the infinite loop?

The only way is to have checkers inside the code that "look" for irregular things. Something like this:

for (var i = 2; i > 0; i++) {
    console.log(i);
    if (i > 100000) break;
}

That line if (i > 100000) break; will interrupt the loop in case it reaches the 100,000 iteration.

  • an addendum, on slow computers or OS requiring a formatting, this type of occurrence may cause browser freezing and keep the system occupied for long periods of time

Browser other questions tagged

You are not signed in. Login or sign up in order to post.