为什么setInterval()会忽略错误?

时间:2014-08-06 23:02:42

标签: javascript function exception setinterval

Javascript' setInterval()似乎不关注它调用的代码是否会引发异常。例如,这不会终止程序,而是一遍又一遍地调用函数:

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

这种行为的原因是什么?是否记录在任何地方?

3 个答案:

答案 0 :(得分:4)

throw的MDN文档说,对于抛出的对象:

  

如果调用函数之间不存在catch块,程序将终止。

这并非严格准确。 ECMAScript spec section 10.4

  

抛出的异常也可能会退出一个或多个执行上下文。

这更准确。

什么是执行上下文?那么,有一个原始程序。进行函数调用时,将在该函数运行时创建嵌套上下文。拨打eval即可拨打电话。 10.4涵盖了这一点。

通常,当抛出异常时,它将向上传递所有嵌套的执行上下文,直到它被捕获,或者它到达外部执行上下文。如果未在执行上下文中捕获,则将终止该上下文。因此,如果您的原始程序是最外层的执行上下文,它将终止于未捕获的异常?

调用处理程序函数时,由于setTimeout间隔到期,是最外层的执行上下文。因此,未捕获的异常终止它,但它不嵌套在您的原始程序中。所以没有其他东西被终止。

处理计时器的线程到期是JS引擎的一部分,所以你也不会终止它。因此,每个间隔一次,在调用处理函数时会创建一个新的执行上下文,因此它会重复。

答案 1 :(得分:1)

如果您不希望一遍又一遍地调用该函数,请捕获异常并清除计时器。此示例从5开始向下计数,打印到控制台,并在值小于零时抛出异常:

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);

由您决定是否应该再次调用该函数。异常停止执行该功能,但没有&#34;程序&#34;终止。网络浏览器是&#34;程序&#34;。如果它运行抛出异常的函数,它仍然继续为其他事件提供服务。这是预期的行为。

为什么它不会在异常时取消定时器?尝试加载可能失败的资源并在成功时清除计时器时,您可能需要这样做。

答案 2 :(得分:0)

当你致电setInterval时,运行时并不知道回调是否会抛出。

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?');

你会发现如果回调抛出, 终止&#34;程序,&#34;这就是回调本身。在此示例中,如果单击“确定”按钮,则回调将不会继续进行console.log调用。它会继续反复调用回调。如果您稍后再次更改shouldThrow,则会在控制台中看到更多消息。