【问题标题】:Is there a way to add try-catch to every function in Javascript?有没有办法为 Javascript 中的每个函数添加 try-catch?
【发布时间】:2012-07-29 08:02:30
【问题描述】:

对于错误报告,我想在我拥有的每个函数的代码周围插入一个 try-catch 包装器。

所以基本上我想替换

function foo(arg){
   bar();
}

...与...

function foo(arg){
    try {
        bar() 
    }
    catch(e){
        customErrorHandler(e)
    }
}

有没有一种方法可以将这种通用的 try-catch 应用到所有函数,而无需手动编辑所有函数?比如修改Function对象的原型?

编辑

为什么我想尝试捕获我的所有功能: 我正在构建一个在 iOS 和 Android 上发布的 HTML5 应用程序。我可以从我目前的基本 javascript 错误报告中看出,即使应用程序在我自己的设备上运行良好,但在其他一些设备上确实会发生错误。

我的目标是双重的:每当某人的设备上发生 javascript 错误时...

  1. 我想通知用户该应用可能无法正常运行
  2. 我想大致知道错误发生在哪里,所以我知道到哪里寻找问题

【问题讨论】:

  • 否 - 如果函数实际上不包含 try-catch,您可以仅将函数的 调用 包装在 try-catch 中,但不能将其内容包装起来。对于它的价值,用 try-catch 语句覆盖你的代码是一个非常糟糕的主意。如果有错误,你应该解决它,不允许它发生,而是通过 try-catch 抑制它。
  • +1 表示希望正确尝试捕获所有功能。不过,我认为您将不得不手动编辑它们。
  • Try-catch 非常昂贵。你确定你要这么做吗?有什么要求?
  • 你也可以用一个try catch将入口点包装到代码中......错误会冒泡。这不一定适用于附加事件处理程序等,但任何嵌套在第一个函数中的函数都会简单地将错误冒泡。
  • @KingOfHypocrites,你的回答听起来很有趣,但我没有完全理解。 “使用单个 try-catch 将入口点包装到代码中”是什么意思?你的意思是我应该把我所有的 javascript 都放在一次尝试中{}?

标签: javascript error-handling try-catch prototype


【解决方案1】:

给定的答案已经很好了,只是想用闭包分享一个新的答案。

定义包装器

const tryCatchWrapper = (executable) => async (...args) => {
    try {
        const result = await executable(...args);
        return result;
    } catch (error) {
        // use any custom handler here
       error.message = `[${executable.name}] - ${error.message}`;
       error.data = {...error.data, input_args: args}
       throw error;
    }
}

你的函数没有 try-catch 包装器

const myFunction = async (x, y) => {
    const sum = x + y;
    if (sum > 10) throw new Error(`sum > 10 custom error`)
    return sum;
}

如何使用

try {
    const wrapperFunction = trycatchWrapper3(myFunction2);
    const output = await wrapperFunction(2, 93)
    console.log(output)
} catch (error) {
    console.error(error)
}

结束

【讨论】:

    【解决方案2】:

    我没有足够的声誉来评论接受的答案。

    我在f.apply 之前添加了一个return 来传递返回值。

    var tcWrapper = function(f) {
        return function() {
            try {
                return f.apply(this, arguments);
            } catch(e) {
                customErrorHandler(e)
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      这并不简单,因为没有办法找到到处定义的所有 JavaScript 函数。例如,任何此类方法都可能会错过在运行时定义的回调函数。

      您也可能不想包装所有函数,因为这将包括浏览器函数和您肯定不想包装的 JavaScript 库中的函数。

      更好的方法可能是定义一个包装另一个函数的函数:

      var tcWrapper = function(f) {
          return function() {
              try {
                  f.apply(this, arguments);
              } catch(e) {
                  customErrorHandler(e)
              }
          }
      }
      

      现在您可以使用此功能来装饰您想要的任何东西。如果使用名称空间,包装会变得更简单:

      var NS = { f: function() {  } }
      

      只需将所有函数包装在一个特殊的命名空间中,然后遍历该命名空间:

      $.each( NS, function(i,n) {
          var p = NS[i];
          if( typeof p === 'function' ) {
              NS[i] = tcWrapper(p);
          }
      } );
      

      【讨论】:

      • 并非所有函数都需要相同的“this”。您可能想知道您发送的是哪个“this”。例如,事件处理程序有时会将 this 作为事件目标或对象方法。但是,您可以遍历对象属性并用 getter(使用 Object.defineProperty)替换它们,该方法将它们包装在一个内联函数中,该函数既可以将它们的 this 修复为一个不能从外部篡改的值,也可以包装它们在 try catch 块中。
      • @nus:我不明白你的意思。我只是通过this 但也许我做错了?也许您的信息太复杂,无法发表评论。在另一个答案中向我们展示代码和原因怎么样?
      • 对不起,我的错误我没有看到 apply 只有在返回的函数已经附加到 NS 时才会运行。我不知何故认为它是在 tcpWrapper 的上下文中调用的,在这种情况下,它会在每个函数上修复来自 tcpWrapper 的this
      【解决方案4】:

      我需要加强一些代码,所以我编写了一个名为 fortify 的函数并将其放入 NPM 模块中。这是一项正在进行的工作,但它应该会有所帮助。

      https://github.com/infinitered/over-armour

      奖励:它适用于异步函数。欢迎反馈

      【讨论】:

        【解决方案5】:

        我想知道(这纯粹是猜测,所以不确定这是否可行)你可以这样做:

        function callTryCatch(functionSignature) {
            try {
                eval(functionSignature);
            } catch (e) {
                customErrorHandler(e);
            }
        }
        
        function entryPoint() {
            callTryCatch(function() {
                // do function logic
            });
        }
        

        同样,这纯粹是猜测,我还没有测试过,但如果可能的话,我认为关键在于 eval 语句。

        【讨论】:

        • 永远不要使用eval;在你的情况下,apply() 做你想做的事。
        【解决方案6】:

        好的,我好像在这里找到了:http://www.nczonline.net/blog/2009/04/28/javascript-error-handling-anti-pattern/

        基本上,所有函数都由 try-catch 包装器替换,其中包含 try 部分中的原始函数。

        【讨论】:

        • 博客文章的标题说这是一种反模式,即可能但不可取。由你决定,但我真的认为这不是一个好主意。
        • 博客文章讨论了反模式,但也展示了解决方案。
        猜你喜欢
        • 1970-01-01
        • 2022-08-13
        • 2017-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多