当前位置:  开发笔记 > 编程语言 > 正文

抛出异常时如何获得JavaScript堆栈跟踪?

如何解决《抛出异常时如何获得JavaScript堆栈跟踪?》经验,为你挑选了11个好方法。

如果我自己抛出JavaScript异常(例如throw "AArrggg"),我如何获得堆栈跟踪(在Firebug中或其他方式)?现在我收到消息.

编辑:正如下面很多人都贴出来,就可以得到一个堆栈跟踪JavaScript异常,但我希望得到一个堆栈跟踪我的异常.例如:

function foo() {
    bar(2);
}
function bar(n) {
    if (n < 2)
        throw "Oh no! 'n' is too small!"
    bar(n-1);
}

foo被调用时,我希望得到一个堆栈跟踪,其中包括在两个电话foo,bar,bar.



1> Eugene Moroz..:

编辑2(2017):

在所有现代浏览器中,您只需调用:console.trace(); (MDN参考)

编辑1(2013):

如原始问题的评论中指出的更好(和更简单)的解决方案是使用对象的stack属性,Error如下所示:

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,调用函数等.

原创(2009年):

此代码段的修改版本可能会有所帮助:

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


错误.stack在IE中未定义,仅适用于chrome和Mozilla firefox
我不确定为什么这不会被投票更多 - 其他答案对我来说效果不佳.顺便说一句,请确保不要将参数视为数组(此处更新的代码段:https://gist.github.com/965603)
看原始问题的评论:你不需要自定义代码,只需使用"抛出新错误('arrrgh')"
请注意,现在不推荐使用`caller`,并且从ES5严格模式中删除`callee`.这就是为什么http://stackoverflow.com/questions/103598/why-was-the-arguments-callee-caller-property-deprecated-in-javascript/235760#235760

2> Jocelyn dela..:

请注意,chrome/chrome(使用V8的其他浏览器)以及Firefox都有一个方便的界面来通过Error对象上的堆栈属性获取堆栈跟踪.

try {
   // Code throwing an exception
} catch(e) {
  console.log(e.stack);
}

它适用于基本异常以及您自己抛出的异常.(认为​​你使用的是Error类,这无论如何都是一种很好的做法).

查看有关V8文档的详细信息


Firefox也支持`.stack`属性.
我希望我可以投票100次!谢谢Jocelyn.它真的帮了很多忙

3> Justin L...:

在Firefox中,您似乎不需要抛出异常.这足够了

e = new Error();
console.log(e.stack);



4> Helephant..:

如果您有firebug,则脚本选项卡中的所有错误选项都会中断.一旦脚本达到你的断点,你可以看看firebug的堆栈窗口:

截图


嗯,这似乎不起作用.它在调试器中阻止了Javascript引发的错误(例如,未定义的变量错误),但是当我抛出自己的异常时,除了"未捕获的异常"消息之外我仍然没有得到任何东西.

5> Gabriel Nahm..:

原始问题的评论中指出的一个好的(简单的)解决方案是使用对象的stack属性,Error如下所示:

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和行号,调用函数等.

我有一个非常精细和漂亮的解决方案,我为我正在进行的项目设计的,我已经提取并重新设计了一些以便进行概括.这里是:

(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.js

确保玩弄Console对象中的设置!您可以在轨迹线之间添加间距并将其完全关闭.这里Console.trace设置为false:

没有踪影

您甚至可以关闭显示的第一位信息(设置Console.settings.debug.showInfofalse)或完全禁用调试(设置Console.settings.debug.enabledfalse),这样您就不必再次注释掉调试语句!让他们进去,这将无能为力.



6> Mark Biek..:

我不认为你可以使用任何内置的东西,但我确实找到了很多人自己动手的例子.

DIY javascript堆栈跟踪

任何浏览器中的Javascript堆栈跟踪



7> Eli Grey..:

即使您抛出它,也可以访问实例的stack(stacktrace在Opera中)属性Error.问题是,你需要确保你使用throw new Error(string)(不要忘记新的而不是throw string.

例:

try {
    0++;
} catch (e) {
    var myStackTrace = e.stack || e.stacktrace || "";
}



8> sbr..:

使用Chrome浏览器,您可以使用以下console.trace方法:https://developer.chrome.com/devtools/docs/console-api#consoletraceobject



9> Konstantin S..:

这将为现代Chrome,Opera,Firefox和IE10 +提供堆栈跟踪(作为字符串数组)

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)使用的标题"错误".

它不应该在旧浏览器上崩溃,而只是返回空数组.如果您需要更多通用解决方案,请查看stacktrace.js.它支持的浏览器列表真的很令人印象深刻,但在我看来,这对于它的小任务非常重要:37Kb的缩小文本,包括所有依赖项.



10> Miller Medei..:

在Firebug上获得真正的堆栈跟踪的一种方法是创建一个真正的错误,比如调用一个未定义的函数:

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()显示堆栈跟踪.



11> Patrick Seym..:

更新Eugene的答案:必须抛出错误对象,以便IE(特定版本?)填充stack属性.以下应该比他当前的例子更好,并且应该避免undefined在IE中返回.

function stackTrace() {
  try {
    var err = new Error();
    throw err;
  } catch (err) {
    return err.stack;
  }
}

注1:这种事情只应在调试时完成,并在实时时禁用,特别是在频繁调用时.注意2:这可能不适用于所有浏览器,但似乎适用于FF和IE 11,这很适合我的需要.

推荐阅读
殉情放开那只小兔子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有