Javascript错误停止代码执行

Javascript错误停止代码执行,javascript,error-handling,Javascript,Error Handling,每当事件处理程序中发生错误时,它会完全停止代码执行,因此不会调用第二个事件回调 例如: $(function() { window.thisDoesntExist(); } $(function() { //Do something unharmful and unrelated to the first event } 在这个(简化的)示例中,通过在两个匿名函数中添加try/catch,您可以很容易地解决这个问题,但实际上,这些函数通常会添加几个其他事件处理程序,这反过来又需

每当事件处理程序中发生错误时,它会完全停止代码执行,因此不会调用第二个事件回调

例如:

$(function() {
    window.thisDoesntExist();
}
$(function() {
    //Do something unharmful and unrelated to the first event
}
在这个(简化的)示例中,通过在两个匿名函数中添加try/catch,您可以很容易地解决这个问题,但实际上,这些函数通常会添加几个其他事件处理程序,这反过来又需要try/catch。我最终得到了充满try/catch块的非常重复的代码

我的项目采用模块化设计,其中每个功能都位于不同的JS中(并在构建过程中连接)。我正在寻找一种更通用的方法来处理每个特性中的错误,这样错误就不会停止其他特性的代码执行

我已经尝试了以下解决方案: -window.onerror(即使在此函数中返回true,代码执行也会停止)
-$(window).error()=>已弃用,代码执行停止

您可以创建一个帮助函数来防止重复相同的样板代码

function tryFunction(f, onerror) {
    try {
        if (typeof f == 'function') {
            return f();
        }
    } catch (e) {
        return onerror(e);
    }
}

$(function() {
    var result = tryFunction(window.thisDoesNotExist, function (error) {
        alert('Whoops: ' + error);
    });
});

。这有点不同,但想法相同。

在调用
myFunction()

并且可以选择将其封装在一个通用函数中,如Bart所说,如果您的函数不存在,则可以选择在控制台中记录错误


如果您的webapp非常庞大,有很多交互和JS,那么太多的
try-catch
可能会改变应用程序的全局性能

我会用一个包装器来尝试类似的东西,它将为您处理try-catch(请参见下面的内容,或此jsfiddle:)

从我(不是,也不是真的)处理这个和参数的方式来看,我想很明显我是从js开始的。但是我希望你明白这个想法,而且它是正确的/有用的

  var wrapper = {
      wrap: function wrap(f) {
          return function (args) {
              try {
                  f.apply(null, args);
              } catch (ex){
                  console.log(f.name+" crashed with args "+args);
              };
          };
      }
  };

  var f1 = function f1Crashes(arg) {
      return window.thisDoesntExist();
  };
  var f2 = function f2Crashes(arg) {
      return window.thisDoesntExist();
  };

  var f3 = function f3MustNotCrash(arg) {
      wrapper.wrap(f1)(arg);
      wrapper.wrap(f2)(arg);
  }

  f3('myarg');

我找到了解决办法。使用setTimeout时,代码在单独的线程中执行,因此不会破坏网页的任何其他部分

$(function() {
    setTimeout(function() {
    window.thisDoesntExist();
    }, 0);
});
$(function() {
    setTimeout(function() {
        //Do something unharmful and unrelated to the first event
        alert("This passes")
    }, 0);
});
在本例中,第二个函数运行,即使第一个函数抛出错误。
这里有一个工作示例:

您在问题中提到的
try
-
catch
模式是正确的方式-您想要
try
-
catch
块,而不是一种静默地处理模块错误的方式(一般来说,在全球范围内处理异常时要非常小心,并且要持续处理,这样才能在6个月后发现数据损坏漏洞)

你真正的问题是:

…实际上,这些函数通常会添加其他几个事件处理程序,而这些事件处理程序又需要try/catch。我最终得到的是充满try/catch块的非常重复的代码

这是一种新的结构,在大多数浏览器中都是本机的,但在速度较慢的浏览器中(ahem,IE)很容易填充,它为您提供了一种管理事件回调和事件异常的标准方法

通过
承诺
您的代码承诺总是做一些事情:要么解决/成功,要么拒绝/失败

function moduleA() {
    return new Promise(function (resolve, reject)
    {
        try{
            var result = window.thisDoesntExist();
            resolve(resolve); // Success!
        }
        catch(err){
            reject(err); // Fail!
        }
    });
}
这更好,因为与在每个回调中嵌套
try
-
catch
块不同,您可以在每个回调中链接承诺:

moduleA().
    then(moduleB).
    then(moduleC).
    catch(errorHandler); // Catch any error from A, B, or C
您还可以处理错误并继续:

moduleA().
    catch(continuableErrorHandler). // Catch any error from A
    then(moduleB).
    then(moduleC).
    catch(errorHandler); // Catch any error from B or C
您仍然需要在回调中使用大量的
try
-
catch
块,但是任何包含在
Promise
中的块都可以以相同的模块化方式处理

JS的下一个功能是
async
wait
,但现在您可以使用transpiler来使用它们。这些功能使用Promission使代码更易于阅读,最重要的是(对您而言)在顶部有一个
try
-
catch
来收集整个
Promise
链中的异常

这个答案已经太长了,但我已经回答了


TL;DR:如果您的问题是“充满try/catch块的非常重复的[event callback]代码”,请尝试改用
Promise

您阅读了我的问题吗?您可以用此(简化)方法轻松解决问题例如,在两个匿名函数中都添加了try/catch,但实际上,这些函数通常会添加其他几个事件处理程序,而这些事件处理程序反过来又需要try/catch。我最终得到的代码非常重复,充满了try/catch块。如果您希望代码尽可能健壮,那么这可能是您必须做出的妥协。@Webberig,我当然可以您需要的基本要求是继续在(任何)上运行代码错误。唯一的方法是使用try-catch。这是第一步。之后,您可以使用错误回调或发出错误事件或其他任何使您的错误处理更加可靠和灵活的方法。您可以参考Requirejs的源代码,它也使用try-catch。总有+1,因为我学到了一些东西-1,因为这是一个超级粗俗的hacksettimeout的引用函数不在单独的线程中运行。JavaScript运行时的执行堆栈是单线程的。实际发生的情况是,当onerror回调处理错误时,执行堆栈将被清除(这就是为什么在错误发生后不会运行其他代码的原因).setTimeout会将引用的函数放置在事件队列中,当执行堆栈清除时,该队列中的事件将运行。它确实可以工作,但不是因为多线程。此外,运行异步时不能保证顺序,这取决于实现,如果这些任务需要按顺序进行,则您将创建一个竞赛c从上下文来看,我假设顺序在这里并不重要,但作为一般解决方案,这是有问题的。