Why is setInterval () ignoring errors?

The Javascript setInterval () seems to be oblivious to whether the code it calls is actually throwing exceptions. For example, this will not terminate the program, but will call the function over and over:

setInterval(function() { throw "error" }, 1000);

      

What is the reason for this behavior? Is this documented anywhere?

+3


source to share


3 answers


The MDN docs for throw

says that for a thrown object:

If there is no catch blocking between the caller's functions, the program will exit.

This is not entirely accurate. ECMAScript 10.4 Specification Section

A thrown exception can also be thrown from one or more execution contexts.

This is more accurate.



What is an execution context? Well, there's one in there for your original program. When you make a call to a function while that function is running, a nested context is created. The call for eval

will do it. 10.4 covers this.

In general, when an exception is thrown, it will traverse all nested execution contexts until it is caught or it reaches the outer execution context. If it does not hit the execution context, that context will be aborted. Thus, if your original program is the outermost execution context, will it fail with an uncaught exception?

When you call a handler function, due to an interval expired setTimeout

, it is the outermost execution context. Thus, the unmapped exception ends it, but it is not nested in your original program. Thus, nothing else stops.

The thread that is processing the timer expires is part of the JS engine, so you are not going to stop that. Thus, once per interval, a new execution context is created when the handler function is called and repeated.

+3


source


If you don't want the function to be called over and over, catch the exception and clear the timer. This example counts down from five, prints to the console, and throws an exception when the value is less than zero:

var counter = 5;
var timer;

var decrement = function() {
    try {
        if ( counter < 0 ) {
            clearInterval(timer);
            throw new Error("Invalid count");
        }
        console.log(counter);
        counter -= 1;
    }
    catch ( error ) {
        console.error(error);
    }
}

timer = setInterval(decrement, 1000);

      



It's up to you whether or not to call the function again or again. An exception stops the execution of the function, but there is no "program" to terminate. A web browser is a "program". If it executes the function that throws the exception, it still continues to service other events. This is expected behavior.

Why doesn't it cancel the timer on exception? This may be required when trying to load a resource that might fail and clear the success timer.

+1


source


When you call setInterval

, the runtime doesn't know if the callback will be thrown.

var shouldThrow = false;
setInterval(function () {
    if (shouldThrow) throw 'error';
    console.log('program has not stopped');
}, 5000);

// nothing is wrong at this point.
// thus, the program continues
shouldThrow = confirm('Throw error?');

      

You will find that if the callback fires, it terminates the "program" that is the callback itself. In this example, if you click OK, the callback will not go to the call console.log

. However, it keeps on calling the callback. If you change again later shouldThrow

, you will see more messages in the console.

0


source







All Articles