当我抛出一个exception时,如何获得一个Javascript堆栈跟踪?
如果我自己抛出一个Javascriptexception(例如throw "AArrggg"
),我怎么能得到堆栈跟踪(在Firebug或其他)? 现在我只是得到消息。
编辑 :由于许多人下面已经发布,有可能得到一个JavaScriptexception的堆栈跟踪,但我想获得一个堆栈跟踪我的例外。 例如:
function foo() { bar(2); } function bar(n) { if (n < 2) throw "Oh no! 'n' is too small!" bar(n-1); }
当foo
被调用的时候,我想得到一个包含对foo
, bar
, bar
的调用的栈跟踪。
这段代码的修改版本可能会有所帮助:
function stacktrace() { function st2(f) { return !f ? [] : st2(f.caller).concat([f.toString().split('(')[0].substring(9) + '(' + f.arguments.join(',') + ')']); } return st2(arguments.callee.caller); }
编辑(2017):
在所有现代浏览器中,您只需调用: console.trace();
(MDN参考)
编辑:
在原始问题的注释中指出的更好(更简单)的解决scheme是使用Error
对象的stack
属性,如下所示:
function stackTrace() { var err = new Error(); return err.stack; }
这将产生这样的输出:
DBX.Utils.stackTrace@http://localhost:49573/assets/js/scripts.js:44 DBX.Console.Debug@http://localhost:49573/assets/js/scripts.js:9 .success@http://localhost:49573/:462 x.Callbacks/c@http://localhost:49573/assets/js/jquery-1.10.2.min.js:4 x.Callbacks/p.fireWith@http://localhost:49573/assets/js/jquery-1.10.2.min.js:4 k@http://localhost:49573/assets/js/jquery-1.10.2.min.js:6 .send/r@http://localhost:49573/assets/js/jquery-1.10.2.min.js:6
给出调用函数的名称以及URL,调用函数等等。
请注意,铬/铬(其他浏览器使用V8)确实有一个方便的接口,通过错误对象上的堆栈属性获取堆栈跟踪。
try { // Code throwing an exception } catch(e) { console.log(e.stack); }
它适用于基本的例外,也适用于你自己抛出的例外。 (考虑到你使用了Error类,这是一个很好的习惯)。
查看V8文档的详细信息
在Firefox中,似乎你不需要抛出exception。 这是足够的
e = new Error(); console.log(e.stack);
如果您有萤火虫,脚本选项卡中的所有错误选项都会中断。 一旦脚本已经达到你的断点,你可以看看萤火虫的堆栈窗口:
我不认为有什么可以使用的东西,但是我find了很多自己滚动的例子。
- DIY的javascript堆栈跟踪
- 任何浏览器的Javascript堆栈跟踪
在原始问题的注释中指出的一个好的(和简单的)解决scheme是使用Error
对象的stack
属性,如下所示:
function stackTrace() { var err = new Error(); return err.stack; }
这将产生这样的输出:
DBX.Utils.stackTrace@http://localhost:49573/assets/js/scripts.js:44 DBX.Console.Debug@http://localhost:49573/assets/js/scripts.js:9 .success@http://localhost:49573/:462 x.Callbacks/c@http://localhost:49573/assets/js/jquery-1.10.2.min.js:4 x.Callbacks/p.fireWith@http://localhost:49573/assets/js/jquery-1.10.2.min.js:4 k@http://localhost:49573/assets/js/jquery-1.10.2.min.js:6 .send/r@http://localhost:49573/assets/js/jquery-1.10.2.min.js:6
给出调用函数的名称以及URL和行号,调用函数等等。
我有一个非常精巧和漂亮的解决scheme,我为当前正在开发的一个项目devise了一个项目,并且已经提取并重新编写了一些项目以进行概括。 这里是:
(function(context){ // Only global namespace. var Console = { //Settings settings: { debug: { alwaysShowURL: false, enabled: true, showInfo: true }, stackTrace: { enabled: true, collapsed: true, ignoreDebugFuncs: true, spacing: false } } }; // String formatting prototype function. if (!String.prototype.format) { String.prototype.format = function () { var s = this.toString(), args = typeof arguments[0], args = (("string" == args || "number" == args) ? arguments : arguments[0]); if (!arguments.length) return s; for (arg in args) s = s.replace(RegExp("\\{" + arg + "\\}", "gi"), args[arg]); return s; } } // String repeating prototype function. if (!String.prototype.times) { String.prototype.times = function () { var s = this.toString(), tempStr = "", times = arguments[0]; if (!arguments.length) return s; for (var i = 0; i < times; i++) tempStr += s; return tempStr; } } // Commonly used functions Console.debug = function () { if (Console.settings.debug.enabled) { var args = ((typeof arguments !== 'undefined') ? Array.prototype.slice.call(arguments, 0) : []), sUA = navigator.userAgent, currentBrowser = { firefox: /firefox/gi.test(sUA), webkit: /webkit/gi.test(sUA), }, aLines = Console.stackTrace().split("\n"), aCurrentLine, iCurrIndex = ((currentBrowser.webkit) ? 3 : 2), sCssBlack = "color:black;", sCssFormat = "color:{0}; font-weight:bold;", sLines = ""; if (currentBrowser.firefox) aCurrentLine = aLines[iCurrIndex].replace(/(.*):/, "$1@").split("@"); else if (currentBrowser.webkit) aCurrentLine = aLines[iCurrIndex].replace("at ", "").replace(")", "").replace(/( \()/gi, "@").replace(/(.*):(\d*):(\d*)/, "$1@$2@$3").split("@"); // Show info if the setting is true and there's no extra trace (would be kind of pointless). if (Console.settings.debug.showInfo && !Console.settings.stackTrace.enabled) { var sFunc = aCurrentLine[0].trim(), sURL = aCurrentLine[1].trim(), sURL = ((!Console.settings.debug.alwaysShowURL && context.location.href == sURL) ? "this page" : sURL), sLine = aCurrentLine[2].trim(), sCol; if (currentBrowser.webkit) sCol = aCurrentLine[3].trim(); console.info("%cOn line %c{0}%c{1}%c{2}%c of %c{3}%c inside the %c{4}%c function:".format(sLine, ((currentBrowser.webkit) ? ", column " : ""), ((currentBrowser.webkit) ? sCol : ""), sURL, sFunc), sCssBlack, sCssFormat.format("red"), sCssBlack, sCssFormat.format("purple"), sCssBlack, sCssFormat.format("green"), sCssBlack, sCssFormat.format("blue"), sCssBlack); } // If the setting permits, get rid of the two obvious debug functions (Console.debug and Console.stackTrace). if (Console.settings.stackTrace.ignoreDebugFuncs) { // In WebKit (Chrome at least), there's an extra line at the top that says "Error" so adjust for this. if (currentBrowser.webkit) aLines.shift(); aLines.shift(); aLines.shift(); } sLines = aLines.join(((Console.settings.stackTrace.spacing) ? "\n\n" : "\n")).trim(); trace = typeof trace !== 'undefined' ? trace : true; if (typeof console !== "undefined") { for (var arg in args) console.debug(args[arg]); if (Console.settings.stackTrace.enabled) { var sCss = "color:red; font-weight: bold;", sTitle = "%c Stack Trace" + " ".times(70); if (Console.settings.stackTrace.collapsed) console.groupCollapsed(sTitle, sCss); else console.group(sTitle, sCss); console.debug("%c" + sLines, "color: #666666; font-style: italic;"); console.groupEnd(); } } } } Console.stackTrace = function () { var err = new Error(); return err.stack; } context.Console = Console; })(window);
看看GitHub (目前v1.2)! 你可以使用它像Console.debug("Whatever");
它将根据Console
的设置,打印输出和堆栈跟踪(或简单的信息/没有额外的东西)。 这是一个例子:
确保使用Console
对象中的设置! 您可以在轨迹线之间添加间距,并将其完全closures。 这里把Console.trace
设置为false
:
您甚至可以closures显示的第一个信息(将Console.settings.debug.showInfo
设置为false
)或者完全禁用debugging(将Console.settings.debug.enabled
设置为false
),以便您不必再次注释debugging语句! 只要让他们进入,这将无能为力。
即使您抛出它,也可以访问Error
实例的stack
(Opera的stack
stacktrace
)属性。 事情是,你需要确保你使用throw new Error(string)
(不要忘记新的,而不是throw string
。
例:
try { 0++; } catch (e) { var myStackTrace = e.stack || e.stacktrace || ""; }
在Firebug上获得真实堆栈跟踪的一种方法是创build一个真正的错误,如调用一个未定义的函数:
function foo(b){ if (typeof b !== 'string'){ // undefined Error type to get the call stack throw new ChuckNorrisError("Chuck Norris catches you."); } } function bar(a){ foo(a); } foo(123);
或者使用console.error()
后跟一个throw
语句,因为console.error()
显示堆栈跟踪。
使用Chrome浏览器,您可以使用console.trace
方法: https : //developer.chrome.com/devtools/docs/console-api#consoletraceobject
Eugene的答案更新:为了使IE(特定版本?)能够填充stack
属性,必须抛出错误对象。 以下应该比他当前的例子更好地工作,并应避免在IE中返回undefined
。
function stackTrace() { try { var err = new Error(); throw err; } catch (err) { return err.stack; } }
注1:这种事情应该只在debugging时才能完成,而在生存时禁用,尤其是在经常调用的情况下。 注2:这可能不适用于所有的浏览器,但似乎在FF和IE 11,这适合我的需要就好了。
这将为现代的Chrome,Opera,Firefox和IE10 +提供堆栈跟踪(作为string数组)
function getStackTrace () { var stack; try { throw new Error(''); } catch (error) { stack = error.stack || ''; } stack = stack.split('\n').map(function (line) { return line.trim(); }); return stack.splice(stack[0] == 'Error' ? 2 : 1); }
用法:
console.log(getStackTrace().join('\n'));
它从堆栈中排除了自己的调用,以及Chrome和Firefox(不包括IE)使用的标题“错误”。
它不应该在旧的浏览器崩溃,但只是返回空数组。 如果你需要更多的通用解决scheme,请看stacktrace.js 。 它支持的浏览器列表真的很让人印象深刻,但在我看来,这是一个很小的任务,它的目标是:37Kb的缩小文本,包括所有的依赖关系。
在谷歌浏览器(版本19.0及更高版本)中,简单地抛出一个exception是完美的。 例如:
/* file: code.js, line numbers shown */ 188: function fa() { 189: console.log('executing fa...'); 190: fb(); 191: } 192: 193: function fb() { 194: console.log('executing fb...'); 195: fc() 196: } 197: 198: function fc() { 199: console.log('executing fc...'); 200: throw 'error in fc...' 201: } 202: 203: fa();
将在浏览器的控制台输出中显示堆栈跟踪:
executing fa... code.js:189 executing fb... code.js:194 executing fc... cdoe.js:199 /* this is your stack trace */ Uncaught error in fc... code.js:200 fc code.js:200 fb code.js:195 fa code.js:190 (anonymous function) code.js:203
希望这个帮助。
<script type="text/javascript" src="https://rawgithub.com/stacktracejs/stacktrace.js/master/stacktrace.js"></script> <script type="text/javascript"> try { // error producing code } catch(e) { var trace = printStackTrace({e: e}); alert('Error!\n' + 'Message: ' + e.message + '\nStack trace:\n' + trace.join('\n')); // do something else with error } </script>
这个脚本会显示错误
function:
function print_call_stack(err) { var stack = err.stack; console.error(stack); }
用例:
try{ aaa.bbb;//error throw here } catch (err){ print_call_stack(err); }
你可以使用这个库http://www.stacktracejs.com/ 。 这很好
从文档
您也可以通过自己的错误来获得堆栈跟踪不可用在IE或Safari 5-
<script type="text/javascript" src="https://rawgithub.com/stacktracejs/stacktrace.js/master/stacktrace.js"></script> <script type="text/javascript"> try { // error producing code } catch(e) { var trace = printStackTrace({e: e}); alert('Error!\n' + 'Message: ' + e.message + '\nStack trace:\n' + trace.join('\n')); // do something else with error } </script>
这个在现代(2017)浏览器(IE11,Opera,Chrome,FireFox,Yandex)中使用的polyfill代码:
printStackTrace: function () { var err = new Error(); var stack = err.stack || /*old opera*/ err.stacktrace || ( /*IE11*/ console.trace ? console.trace() : "no stack info"); return stack; }
其他答案:
function stackTrace() { var err = new Error(); return err.stack; }
不在IE 11中工作!
使用arguments.callee.caller – 在任何浏览器中都不能在严格模式下工作!
在Firefox上获取堆栈跟踪比在IE上更容易,但基本上这是你想要做的:
将“有问题的”代码包装在try / catch块中:
try { // some code that doesn't work var t = null; var n = t.not_a_value; } catch(e) { }
如果您将检查“错误”对象的内容,它包含以下字段:
e.fileName:问题来自e.lineNumber的源文件/页面:出现问题的文件/页面中的行号e.message:描述发生什么types错误的简单消息e.name:types发生错误,在上面的例子中应该是'TypeError'e.stack:包含导致exception的堆栈跟踪
我希望这可以帮助你。
那种晚了,但是,这里是另一种解决scheme,如果arguments.callee可用,它会自动检测,如果不是,则使用新的Error()。 testing铬,Safari和Firefox。
2个变体 – stackFN(n)为您提供了函数n的名字,并且stackArray()为您提供了一个数组,stackArray()[0]是直接调用者。
试试在http://jsfiddle.net/qcP9y/6/
// returns the name of the function at caller-N // stackFN() = the immediate caller to stackFN // stackFN(0) = the immediate caller to stackFN // stackFN(1) = the caller to stackFN's caller // stackFN(2) = and so on // eg console.log(stackFN(),JSON.stringify(arguments),"called by",stackFN(1),"returns",retval); function stackFN(n) { var r = n ? n : 0, f = arguments.callee,avail=typeof f === "function", s2,s = avail ? false : new Error().stack; if (s) { var tl=function(x) { s = s.substr(s.indexOf(x) + x.length);}, tr = function (x) {s = s.substr(0, s.indexOf(x) - x.length);}; while (r-- >= 0) { tl(")"); } tl(" at "); tr("("); return s; } else { if (!avail) return null; s = "f = arguments.callee" while (r>=0) { s+=".caller"; r--; } eval(s); return f.toString().split("(")[0].trim().split(" ")[1]; } } // same as stackFN() but returns an array so you can work iterate or whatever. function stackArray() { var res=[],f = arguments.callee,avail=typeof f === "function", s2,s = avail ? false : new Error().stack; if (s) { var tl=function(x) { s = s.substr(s.indexOf(x) + x.length);}, tr = function (x) {s = s.substr(0, s.indexOf(x) - x.length);}; while (s.indexOf(")")>=0) { tl(")"); s2= ""+s; tl(" at "); tr("("); res.push(s); s=""+s2; } } else { if (!avail) return null; s = "f = arguments.callee.caller" eval(s); while (f) { res.push(f.toString().split("(")[0].trim().split(" ")[1]); s+=".caller"; eval(s); } } return res; } function apple_makes_stuff() { var retval = "iPhones"; var stk = stackArray(); console.log("function ",stk[0]+"() was called by",stk[1]+"()"); console.log(stk); console.log(stackFN(),JSON.stringify(arguments),"called by",stackFN(1),"returns",retval); return retval; } function apple_makes (){ return apple_makes_stuff("really nice stuff"); } function apple () { return apple_makes(); } apple();
我不得不调查与IE11 smartgwt无限recursion,所以为了深入调查,我需要一个堆栈跟踪。 问题是,我无法使用开发控制台,因为复制更困难的方式。
在javascript方法中使用以下内容:
try{ null.toString(); } catch(e) { alert(e.stack); }
哇 – 我6年没有见到一个人,build议我们在使用前先检查stack
是否可用! 在error handling程序中可以做的最糟糕的事情是抛出一个错误,因为调用了一些不存在的东西。
正如其他人所说,虽然stack
现在大多是安全的,但在IE9或更早版本中不支持。
我logging我的意外错误和堆栈跟踪是非常重要的。 为了获得最大支持,我首先检查是否存在Error.prototype.stack
并且是一个函数。 如果是这样,那么使用error.stack
是安全的。
window.onerror = function (message: string, filename?: string, line?: number, col?: number, error?: Error) { // always wrap error handling in a try catch try { // get the stack trace, and if not supported make our own the best we can var msg = (typeof Error.prototype.stack == 'function') ? error.stack : "NO-STACK " + filename + ' ' + line + ':' + col + ' + message; // log errors here or whatever you're planning on doing alert(msg); } catch (err) { } };
编辑:看来,由于stack
是一个属性,而不是一个方法,你可以安全地调用它,即使在旧的浏览器。 我仍然困惑,因为我非常确定检查Error.prototype
以前为我工作,现在它不 – 所以我不知道发生了什么事情。
使用console.error(e.stack)
Firefox只显示日志中的console.error(e.stack)
,Chrome也显示消息。 如果消息包含重要信息,这可能是一个不好的惊喜。 始终logging两者。
function stacktrace(){ return (new Error()).stack.split('\n').reverse().slice(0,-2).reverse().join('\n'); }
这是一个答案,给你最大的性能(IE 6+)和最大的兼容性。 与IE 6兼容!
function stacktrace( log_result ) { var trace_result; // IE 6 through 9 compatibility // this is NOT an all-around solution because // the callee property of arguments is depredicated /*@cc_on // theese fancy conditinals make this code only run in IE trace_result = (function st2(fTmp) { // credit to Eugene for this part of the code return !fTmp ? [] : st2(fTmp.caller).concat([fTmp.toString().split('(')[0].substring(9) + '(' + fTmp.arguments.join(',') + ')']); })(arguments.callee.caller); if (log_result) // the ancient way to log to the console Debug.write( trace_result ); return trace_result; @*/ console = console || Console; // just in case if (!(console && console.trace) || !log_result){ // for better performance in IE 10 var STerror=new Error(); var unformated=(STerror.stack || STerror.stacktrace); trace_result = "\u25BC console.trace" + unformated.substring(unformated.indexOf('\n',unformated.indexOf('\n'))); } else { // IE 11+ and everyone else compatibility trace_result = console.trace(); } if (log_result) console.log( trace_result ); return trace_result; } // test code (function testfunc(){ document.write( "<pre>" + stacktrace( false ) + "</pre>" ); })();
你试一试
throw new Error('some error here')
这对于Chrome来说非常适用: