660 Stimmen

Wie kann ich einen JavaScript-Stack-Trace erhalten, wenn ich eine Ausnahme auslöse?

Wenn ich selbst eine JavaScript-Ausnahme auslöse (z. B., throw "AArrggg" ), wie kann ich den Stack-Trace (in Firebug oder anders) erhalten? Im Moment bekomme ich nur die Meldung.

bearbeiten : Wie viele der unten genannten Personen gepostet haben, ist es möglich, einen Stack-Trace für eine JavaScript-Ausnahme aber ich möchte einen Stack-Trace für meine Ausnahmen. Zum Beispiel:

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

Wenn foo aufgerufen wird, möchte ich eine Stapelverfolgung erhalten, die die Aufrufe an foo , bar , bar .

970voto

Eugene Morozov Punkte 13864

Bearbeiten 2 (2017):

In allen modernen Browsern können Sie einfach aufrufen: console.trace(); (MDN-Referenz)

Bearbeiten 1 (2013):

Eine bessere (und einfachere) Lösung, auf die in den Kommentaren zur ursprünglichen Frage hingewiesen wurde, ist die Verwendung der stack Eigenschaft eines Error Objekt wie folgt:

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

Dies führt zu einer Ausgabe wie dieser:

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

Angabe des Namens der aufrufenden Funktion zusammen mit der URL, ihrer aufrufenden Funktion usw.

Original (2009):

Eine modifizierte Version von dieser Ausschnitt kann etwas helfen:

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

223voto

Jocelyn delalande Punkte 4596

Beachten Sie, dass Chromium/Chrome (andere Browser, die V8 verwenden) und auch Firefox eine bequeme Schnittstelle haben, um einen Stacktrace durch eine Stapel Eigentum an Fehler Objekte.

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

Das gilt sowohl für die Basisausnahmen als auch für die Ausnahmen, die Sie selbst machen. (Vorausgesetzt, Sie verwenden die Klasse Error, was ohnehin eine gute Praxis ist).

Siehe Details auf V8-Dokumentation

87voto

Justin L. Punkte 3762

In Firefox scheint es, dass Sie die Ausnahme nicht auslösen müssen. Es reicht, wenn Sie

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

26voto

Helephant Punkte 16198

Wenn Sie Firebug haben, gibt es eine Pause auf alle Fehler Option in der Registerkarte Skript. Sobald das Skript den Haltepunkt erreicht hat, können Sie sich das Stack-Fenster von Firebug ansehen:

screenshot

18voto

Gabriel Nahmias Punkte 820

Eine gute (und einfache) Lösung, auf die in den Kommentaren zur ursprünglichen Frage hingewiesen wurde, ist die Verwendung der stack Eigenschaft eines Error Objekt wie folgt:

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

Dies führt zu einer Ausgabe wie dieser:

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

Angabe des Namens der aufrufenden Funktion zusammen mit der URL und der Zeilennummer, ihrer aufrufenden Funktion usw.

Ich habe eine wirklich ausgeklügelte und hübsche Lösung, die ich mir für ein Projekt ausgedacht habe, an dem ich gerade arbeite, und ich habe sie extrahiert und ein wenig überarbeitet, um sie zu verallgemeinern. Hier ist sie:

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

Überprüfen Sie es auf GitHub (derzeit v1.2)! Sie können es verwenden wie Console.debug("Whatever"); und wird, je nach den Einstellungen in Console die Ausgabe und einen Stack-Trace ausgeben (oder nur einfache Informationen/gar nichts). Hier ist ein Beispiel:

Console.js

Spielen Sie unbedingt mit den Einstellungen in der Console Objekt! Sie können Abstände zwischen den Linien der Kurve einfügen und sie ganz ausschalten. Hier ist es mit Console.trace eingestellt auf false :

No trace

Sie können sogar den ersten Teil der angezeigten Informationen ausschalten (setzen Sie Console.settings.debug.showInfo a false ) oder deaktivieren Sie die Fehlersuche vollständig (setzen Sie Console.settings.debug.enabled a false ), damit Sie nie wieder eine Debug-Anweisung auskommentieren müssen! Lassen Sie sie einfach drin und es wird nichts passieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X