为了简化调试,我正在捕获Chrome中的所有控制台日志,以便提交反馈条目的用户也会将所有日志提交到我们的服务器。当有人遇到生产中的问题时,我首先可以让他们重新开始工作,这样我就可以坐下来更彻底地查看所有日志,以确定用户在生产中遇到的任何问题的根本原因。
我用来捕获日志的技术涉及覆盖console.log,以便在第一个参数中输入的所有文本都存储在一个数组中,同时调用遗留函数,这样我仍然可以在控制台中看到日志。 / p>
问题在于偶尔会发生未捕获的异常。这些不包含在上传的日志中,因此并不总是清楚导致问题的原因。所以我尝试通过编写一个将函数作为参数的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:
来测试返回的函数,即新的ReferenceErrorthrow new ReferenceError("YES!! IT WORKS! HAHAHA!");
控制台上的结果输出是:
ReferenceError:YES !!有用! 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打包应用。
答案 0 :(得分:12)
出于同样的原因,我做了很多研究:我想记录错误并报告它们。
“覆盖”原生类型(无论ReferenceError
,String
还是Array
)是不可能的。
Chrome会在运行任何Javascript之前绑定这些内容,因此重新定义window.ReferenceError
无效。
您可以使用ReferenceError
扩展ReferenceError.prototype.extension = function() { return 0; }
,甚至覆盖toString
(为了保持一致性,请在页面上尝试,而不是开发工具)。
这对你没有多大帮助。
但不要担心....
(1)使用window.onerror
获取未捕获错误的文件名,1索引行号和0索引位置,以及错误本身。
var errorData = [];
onerror = function(message, file, line, position, error) {
errorData.push({message:message, file:file, line:line, position:position, error:error});
};
有关示例,请参阅fiddle。由于OP是特定于Chrome的,因此仅在Chrome中进行了测试。
(2)由于对(1)的改进,不再需要这样做,但为了完整起见,我在这里留下了第二种技术,因为onerror
是not guaranteed to work for all errors on all browsers。您有时也会看到以下内容:
var errors = [];
function protectedFunction(f) {
return function() {
try {
f.apply(this, arguments);
} catch(e) {
errors.push(e);
throw e;
}
};
}
setTimeout = protectedFunction(setTimeout);
setInterval = protectedFunction(setInterval);
etc...
仅供参考,所有这些与我在{+ 3}}中的Google Closure Compiler库中所做的非常类似,它是在Gmail开发过程中创建的,目的是为了做到这一点。特别感兴趣的是goog.debug.ErrorHandler
和goog.debug.ErrorReporter
。