繁体   English   中英

Javascript错误会停止代码执行

[英]Javascript error stops code execution

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

例如:

$(function() {
    window.thisDoesntExist();
}
$(function() {
    //Do something unharmful and unrelated to the first event
}

您可以通过在两个匿名函数中添加try / catch来轻松解决此(简化)示例中的问题,但实际上这些函数通常会添加其他几个事件处理程序,而这些处理程序又需要try / catch。 我最终得到了带有try / catch块的非常重复的代码。

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

我已经尝试过以下解决方案: - window.onerror(即使你在这个函数中返回true,代码执行也停止了) - $(window).er​​ror()=>不推荐使用并且代码执行停止

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

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()之前调用if (typeof myFunction == 'function') myFunction()

并且可选地将其包装在像Bart所说的通用函数中,以便在您的函数不存在时可以选择在控制台中记录错误。

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

我会尝试这样的东西用一个包装器来处理你的try catch(见下文,或者这个jsfiddle: http//jsfiddle.net/TVfCj/2/

从我(不是,而不是真的)处理这个和论点的方式来看,我想很明显我是从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');

您在问题中尝试尝试的try catch模式是正确的方法 - 您希望 try - catch块, 而不是静默地通过模块错误(通常总是非常小心地处理全局和持续的异常,这种方式是数据损坏6个月之后你才发现的错误)。

你真正的问题是:

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

对此的解决方案是Promise 这是一种新结构,在大多数浏览器中都是原生的,但在慢速浏览器中很容易填充(ahem,IE),这为您提供了一种管理事件回调事件异常的标准方法。

使用Promise您的代码会承诺始终执行某些操作:解析/成功或拒绝/失败。

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中的下一个是asyncawait ,但你现在可以使用它们与一个转换器。 这些使用promises来使代码更容易阅读,最重要的是(对你而言)只有一次try - 在顶部catch整个Promise链中的异常。

这个答案已经太长了,但我已经在博客中详细介绍了这一点

TL; DR:如果您的问题是“非常重复[事件回调]代码填充了try / catch块”,请尝试使用Promise

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

$(function() {
    setTimeout(function() {
    window.thisDoesntExist();
    }, 0);
});
$(function() {
    setTimeout(function() {
        //Do something unharmful and unrelated to the first event
        alert("This passes")
    }, 0);
});

在此示例中,即使第一个函数抛出错误,也会运行第二个函数。 这是一个有效的例子: http//jsfiddle.net/mathieumaes/uaEsy/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM