简体   繁体   English

Javascript错误会停止代码执行

[英]Javascript error stops code execution

Whenever an error occurs inside an event handler, it stops code execution entirely so the second event callback isn't called. 每当事件处理程序内发生错误时,它就会完全停止代码执行,因此不会调用第二个事件回调。

For example: 例如:

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

You can easily solve the problem in this (simplified) example by adding try/catch in both anonymous functions, but in reality these functions often add several other event handlers which in turn would require try/catch. 您可以通过在两个匿名函数中添加try / catch来轻松解决此(简化)示例中的问题,但实际上这些函数通常会添加其他几个事件处理程序,而这些处理程序又需要try / catch。 I end up with very repetitive code stuffed with try/catch blocks. 我最终得到了带有try / catch块的非常重复的代码。

My projects has a modular design where each feature is in a different JS (and gets concatenated during a build process). 我的项目采用模块化设计,每个功能都在不同的JS中(并在构建过程中连接)。 I'm looking for a more generic way to handle errors inside each feature so that the error doesn't stop code execution of the other features. 我正在寻找一种更通用的方法来处理每个功能中的错误,以便错误不会停止其他功能的代码执行。

I already tried following solutions: - window.onerror (even if you return true in this function, code execution is stopped) - $(window).error() => deprecated and code execution stops 我已经尝试过以下解决方案: - window.onerror(即使你在这个函数中返回true,代码执行也停止了) - $(window).er​​ror()=>不推荐使用并且代码执行停止

You could create a helper function to prevent duplication of the same boilerplate code. 您可以创建一个辅助函数来防止重复相同的样板代码。

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

I created a little demonstration . 我创建了一个小演示 It's slightly different but the same idea. 它略有不同,但同样的想法。

You can simply call if (typeof myFunction == 'function') before calling myFunction() 你可以在调用myFunction()之前调用if (typeof myFunction == 'function') myFunction()

And optionally wrap it in a generic function like said by Bart to have the choice to log an error in the console if your function does not exists. 并且可选地将其包装在像Bart所说的通用函数中,以便在您的函数不存在时可以选择在控制台中记录错误。

If your webapp is huge with many interaction and JS, too many try catch could alter the global performance of your application. 如果您的webapp很多,有很多交互和JS,那么try catch太多会改变应用程序的全局性能。

I would try something like this with a wrapper which will handle the try catch for you (see below, or this jsfiddle : http://jsfiddle.net/TVfCj/2/ ) 我会尝试这样的东西用一个包装器来处理你的try catch(见下文,或者这个jsfiddle: http//jsfiddle.net/TVfCj/2/

From the way I'm (not, and not really) handling the this and the arguments, I guess it's obvious I'm beginning with js. 从我(不是,而不是真的)处理这个和论点的方式来看,我想很明显我是从js开始的。 But I hope you get the idea, and it is correct/useful. 但我希望你能得到这个想法,这是正确/有用的。

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

The try - catch pattern you mention attempting in your question is the correct way - you want try - catch blocks, not a way to silently truck through module errors (in general always be extremely careful handling exceptions globally and continuing, that way lies data corruption bugs you only find 6 months later). 您在问题中尝试尝试的try catch模式是正确的方法 - 您希望 try - catch块, 而不是静默地通过模块错误(通常总是非常小心地处理全局和持续的异常,这种方式是数据损坏6个月之后你才发现的错误)。

Your real problem is this: 你真正的问题是:

... in reality these functions often add several other event handlers which in turn would require try/catch. ...实际上,这些函数通常会添加其他几个事件处理程序,而这些处理程序又需要try / catch。 I end up with very repetitive code stuffed with try/catch blocks. 我最终得到了带有try / catch块的非常重复的代码。

The fix for that is Promise . 对此的解决方案是Promise This is a new structure, native in most browsers but easily shimmed in the slow ones (ahem, IE), that gives you a standard way of managing both the event callback and the exception from the event. 这是一种新结构,在大多数浏览器中都是原生的,但在慢速浏览器中很容易填充(ahem,IE),这为您提供了一种管理事件回调事件异常的标准方法。

With a Promise your code makes a promise to always do something: either resolve/succeed or reject/fail. 使用Promise您的代码会承诺始终执行某些操作:解析/成功或拒绝/失败。

function moduleA() {
    return new Promise(function (resolve, reject)
    {
        try{
            var result = window.thisDoesntExist();
            resolve(resolve); // Success!
        }
        catch(err){
            reject(err); // Fail!
        }
    });
}

This is better because rather than nest try - catch blocks in each callback you can instead chain promises: 这是更好的,因为而不是嵌套try - catch块在每个回调中,你可以改为链接承诺:

moduleA().
    then(moduleB).
    then(moduleC).
    catch(errorHandler); // Catch any error from A, B, or C

You can also handle an error and continue: 您还可以处理错误并继续:

moduleA().
    catch(continuableErrorHandler). // Catch any error from A
    then(moduleB).
    then(moduleC).
    catch(errorHandler); // Catch any error from B or C

You'll still need lots of try - catch blocks in callbacks, but anything that has been wrapped in a Promise can be treated in the same modular way. 在回调中你仍然需要大量的try - catch块,但是任何包含在Promise都可以用同样的模块方式处理。

Coming next in JS is async and await , but you can use them now with a transpiler. JS中的下一个是asyncawait ,但你现在可以使用它们与一个转换器。 These use promises to make code that is much easier to read, and most importantly (for you) have a single try - catch at the top that gathers exceptions from the entire Promise chain. 这些使用promises来使代码更容易阅读,最重要的是(对你而言)只有一次try - 在顶部catch整个Promise链中的异常。

This answer is already too long, but I've blogged about that in more detail . 这个答案已经太长了,但我已经在博客中详细介绍了这一点

TL;DR: If your problem is "very repetitive [event callback] code stuffed with try/catch blocks" try using Promise instead. TL; DR:如果您的问题是“非常重复[事件回调]代码填充了try / catch块”,请尝试使用Promise

I found a solution. 我找到了解决方案。 When using setTimeout, the code is executed in a seperate thread, therefor it won't break any other parts of the webpage. 使用setTimeout时,代码在单独的线程中执行,因此它不会破坏网页的任何其他部分。

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

In this example, the second function is run, even when the first one throws an error. 在此示例中,即使第一个函数抛出错误,也会运行第二个函数。 Here's a working example: http://jsfiddle.net/mathieumaes/uaEsy/ 这是一个有效的例子: http//jsfiddle.net/mathieumaes/uaEsy/

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

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