【发布时间】:2013-07-16 18:51:22
【问题描述】:
为了使调试更容易,我在 Chrome 中捕获了所有控制台日志,以便提交反馈条目的用户也将所有日志提交到我们的服务器。当有人在生产中遇到问题时,我首先可以让他们恢复工作,这样我就可以坐下来更彻底地查看所有日志,以确定用户在生产中遇到的任何问题的根本原因。
我用来捕获日志的技术涉及覆盖 console.log,以便在第一个参数中输入的所有文本都存储在一个数组中,同时调用旧函数,这样我仍然可以在控制台中看到日志。
问题在于偶尔会出现未捕获的异常。这些不包含在上传的日志中,因此并不总是清楚导致问题的原因。所以我尝试通过编写一个 JavaScript 函数来覆盖 ReferenceError,该函数接受一个函数作为参数,然后返回一个新函数来处理它,比如将数据存储在一个变量中,然后在最后一步调用旧函数:
function overrideException(legacyFn) {
/** arguments for original fn **/
return function() {
var args = [];
args[0] = arguments[0];
// pass in as arguments to original function and store result to
// prove we overrode the ReferenceError
output = ">> " + legacyFn.apply(this, args).stack;
return legacyFn.apply(this, arguments);
}
}
为了测试 overrideException 函数,我在控制台上运行了以下代码:
ReferenceError = overrideException(ReferenceError);
之后,我通过手动抛出 ReferenceError 来测试返回的函数,新的 ReferenceError:
throw new ReferenceError("YES!! IT WORKS! HAHAHA!");
控制台上的结果输出是:
参考错误:是的!有用!哈哈哈!
从 overrideException 函数检查全局变量 output 表明它确实运行了:
output
">> ReferenceError: YES!! IT WORKS! HAHAHA!
at ReferenceError (<anonymous>)
at new <anonymous> (<anonymous>:18:35)
at <anonymous>:2:7
at Object.InjectedScript._evaluateOn (<anonymous>:562:39)
at Object.InjectedScript._evaluateAndWrap (<anonymous>:521:52)
at Object.InjectedScript.evaluate (<anonymous>:440:21)"
现在,事情开始分崩离析。在我们的代码中,我们不知道何时发生未捕获的异常,因此我尝试运行一个不存在的函数来测试它:
ttt();
结果:
ReferenceError: ttt 未定义
但是,与我们显式抛出错误的情况不同,在这种情况下,函数不会触发,我们只剩下遗留功能。变量output的内容与第一次测试相同。
所以问题似乎是这样的:我们如何覆盖 JavaScript 引擎用来抛出错误的 ReferenceError 功能,使其与我们在抛出 ReferenceError 时使用的功能相同?
请记住,目前我的问题仅限于 Chrome;我正在构建一个 Chrome 打包应用程序。
【问题讨论】:
-
猜测您不想将代码包装在
try/catch中,然后处理错误对象然后重新抛出? -
@CrazyTrain - 我可以做到,而且我可能会做到。然而,这很乏味,也可能会错过一些东西。我喜欢防伪且包罗万象的解决方案,因为它们通常也是“防我太忙” :) 我的计划当然是使用更多的 try/catch,但这似乎是一个非常好的解决方案,所以我开始深入研究它。
-
我的意思是一个整体的
try/catch,它包含了你所有的代码。由于似乎目标不是处理适当的错误,而是以某种方式重新格式化它们,因此将所有代码包装在单个try/catch中似乎与您当前替换构造函数的方法没有什么不同。你只需要确保你重新抛出你得到的任何错误。 -
@CrazyTrain - 我确实考虑过,但随后整个应用程序将停止工作......嗯......或者它会......我可能只是出于好奇而尝试你的建议,但我真的很想看看如何覆盖这些原生 Error 对象。 :)
-
@CrazyTrain - 这是一个创造性的建议,但问题是 try/catch 中的代码仅在页面最初加载并加载所有其他函数和事件处理程序时运行一次。一旦运行,它就不再运行,因此每个函数和事件处理程序仍然需要自己独立的 try/catch 块。希望这会有所帮助!
标签: javascript google-chrome google-chrome-devtools chromium developer-tools