Jak mogę uzyskać śledzenie stosu JavaScript po zgłoszeniu wyjątku?

519

Jeśli sam wygeneruję wyjątek JavaScript (np. throw "AArrggg"), Jak mogę uzyskać ślad stosu (w Firebug lub w inny sposób)? Właśnie dostaję wiadomość.

edytować : Jak wiele osób poniżej opublikowało, możliwe jest uzyskanie śledzenia stosu dla wyjątku JavaScript, ale chcę uzyskać ślad stosu dla moich wyjątków. Na przykład:

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

Kiedy foo nazywa, chcę uzyskać ślad stosu, który zawiera połączenia do foo, bar, bar.

David Wolever
źródło
1
możliwy duplikat śledzenia stosu wyjątków Javascript
ripper234
Błąd jest nadal otwarty w narzędziu do śledzenia błędów Firebug od 2008 roku: code.google.com/p/fbug/issues/detail?id=1260 - oznacz go gwiazdką!
Miller Medeiros
13
Odpowiedź powinna brzmieć „wyrzuć nowy błąd („ arrrgh ”);” zobacz tę ładnie napisaną stronę: devthought.com/2011/12/22/a-string-is-not-an-error
eleganckie kości
1
(2013) Możesz teraz wyświetlać ślady stosu w Firebug na Firefox, nawet jeśli jest to po prostu throw 'arrrgh';i wyglądają tak samo jak w przypadku throw new Error('arrrgh');. Debuger Chrome nadal wymaga throw new Error('arrrgh');jednak, jak wspomniano (ale Chrome wydaje się dawać znacznie bardziej szczegółowe ślady).
user56reinstatemonica8,
26
@ChetanSastry I googowałem po „javascript stack trace” i to był pierwszy wynik
David Sykes

Odpowiedzi:

755

Edycja 2 (2017):

We wszystkich nowoczesnych przeglądarkach możesz po prostu zadzwonić: console.trace(); (MDN Reference)

Edycja 1 (2013):

Lepszym (i prostszym) rozwiązaniem, jak wskazano w komentarzach do pierwotnego pytania, jest użycie stackwłaściwości Errorobiektu w następujący sposób:

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

To wygeneruje dane wyjściowe w następujący sposób:

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

Podanie nazwy funkcji wywołującej wraz z adresem URL, funkcją wywołującą itd.

Oryginał (2009):

Zmodyfikowana wersja tego fragmentu może nieco pomóc:

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);
}
Eugene Morozov
źródło
11
Nie jestem pewien, dlaczego nie jest to więcej głosowane - inne odpowiedzi nie działały tak dobrze dla mnie. BTW, pamiętaj, aby nie traktować argumentów jako tablicy (zaktualizowany fragment tutaj: gist.github.com/965603 )
ripper234
1
nie działa w chrome, tacktrace (): [Wyjątek: TypeError: Object # <Object> nie ma metody
hetaoblog
3
zobacz komentarz do oryginalnego pytania: nie potrzebujesz niestandardowego kodu, po prostu użyj „wyrzuć nowy błąd ('arrrgh')”
Joshua Richardson
16
Error.stack jest niezdefiniowany w IE, działa tylko w chrome i Mozilli Firefox
Philipp Munin
4
Pamiętaj, że callerjest on przestarzały i calleezostał usunięty z trybu ścisłego ES5. Oto dlaczego stackoverflow.com/questions/103598/…
PhilT
187

Zauważ, że chrom / chrome (inne przeglądarki używające V8), a także Firefox mają wygodny interfejs, aby uzyskać śledzenie stosu poprzez właściwość stosu na obiektach Error .

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

Dotyczy to zarówno wyjątków podstawowych, jak i tych, które sam sobie rzucasz. (Uważa się, że korzystasz z klasy Error, co zresztą jest dobrą praktyką).

Zobacz szczegółowe informacje na temat dokumentacji V8

Jocelyn delalande
źródło
12
Firefox obsługuje również tę .stackwłaściwość.
kennytm
2
Chciałbym móc głosować 100 razy! Dziękuję Jocelyn. Naprawdę bardzo pomogło
safrazik
1
możesz także użyć, console.error(e.stack);aby wyglądał jak domyślny komunikat wyjątku
Bruno Peres,
80

W Firefoksie wydaje się, że nie musisz rzucać wyjątku. Wystarczy to zrobić

e = new Error();
console.log(e.stack);
Justin L.
źródło
Działa również w aplikacjach mobilnych (zbudowanych przy użyciu JQM).
Samik R
Działa również w Chromium (w każdym razie wersja 43).
Andy Beverley,
W przeglądarce Firefox 59 nie działa to po wywołaniu przez window.onerror, pokazuje prawie pusty stos tylko z onerrorfunkcją.
Code4R7
Co więcej, możesz zrobić: console.log(new Error().stack)> :( > :( > :(
Andrew
25

Jeśli masz firebuga, w zakładce skryptu występuje przerwa na wszystkie błędy. Gdy skrypt osiągnie punkt przerwania, możesz spojrzeć na okno stosu firebuga:

zrzut ekranu

Pomocnik
źródło
5
Hmm, to chyba nie działa. Zatrzymuje mnie to w debugerze błędów zgłaszanych przez Javascript (np. Niezdefiniowane błędy zmiennych), ale kiedy zgłaszam własne wyjątki, nadal nie dostaję nic poza komunikatem „Nieprzechwycony wyjątek”.
David Wolever,
11

Dobrym (i prostym) rozwiązaniem, jak wskazano w komentarzach do pierwotnego pytania, jest użycie stackwłaściwości Errorobiektu w następujący sposób:

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

To wygeneruje dane wyjściowe w następujący sposób:

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

Podanie nazwy funkcji wywołującej wraz z adresem URL i numerem linii, funkcją wywołującą itd.

Mam naprawdę skomplikowane i ładne rozwiązanie, które opracowałem dla projektu, nad którym obecnie pracuję, a ja je trochę wyodrębniłem i przerobiłem, aby je uogólnić. Oto on:

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

Sprawdź to na GitHub (obecnie v1.2)! Możesz go używać w podobny sposób Console.debug("Whatever");i, w zależności od ustawień Console, wydrukuje dane wyjściowe i ślad stosu (lub po prostu proste informacje / nic więcej). Oto przykład:

Console.js

Pamiętaj, aby pobawić się ustawieniami w Consoleobiekcie! Możesz dodać odstępy między liniami śledzenia i całkowicie je wyłączyć. Tutaj jest Console.traceustawione na false:

Bez śladu

Możesz nawet wyłączyć pierwszy bit wyświetlanych informacji (ustawić Console.settings.debug.showInfona false) lub całkowicie wyłączyć debugowanie (ustawić Console.settings.debug.enabledna false), dzięki czemu nigdy nie będziesz musiał ponownie komentować instrukcji debugowania! Wystarczy je zostawić, a to nic nie da.

Gabriel Nahmias
źródło
10

Nie sądzę, żeby było coś wbudowanego, z czego można by korzystać, ale znalazłem wiele przykładów ludzi, którzy sami sobie wymyślili.

Mark Biek
źródło
Ach, dziękuję - pierwszy link wydaje się, że może to zrobić (chociaż brak obsługi rekurencji może sprawić, że będzie niewykonalny).
David Wolever
Tak, nie widziałem żadnego, który wspierałby rekurencję na pierwszy rzut oka. Będę ciekawy, czy jest na to dobre rozwiązanie.
Mark Biek
1
Myślę, że drugi link powinien obsługiwać rekursję w Firefoksie i Operze, ponieważ używa śledzenia stosu błędów, zamiast ręcznie budować jeden za pomocą zmiennej arguments. Chciałbym usłyszeć, czy znajdziesz rozwiązanie problemu z rekurencją dla różnych przeglądarek (pierwszy artykuł jest mój). :)
Helephant
Helephant: Drugi nie będzie tutaj działał, ponieważ kiedy złapię wyjątek, jest to „ciąg” (tj. Brak „e.stack”): foo = function () {throw „Arg”; } spróbuj {foo (); } catch (e) {/ * typeof e == "string" * /} Może źle to wyrzucam? (rozpocznij obowiązkowe powiedzenie o tym, jak głupie są samouczki Javascript ...)
David Wolever
Spróbuj rzucić obiektu: throw { name: 'NameOfException', message: 'He's dead, Jim' }.
Aaron Digulla,
7

Możesz uzyskać dostęp do właściwości stack( stacktracew Operze) Errorinstancji, nawet jeśli ją rzuciłeś. Chodzi o to, że musisz upewnić się, że używasz throw new Error(string)(nie zapomnij o nowym zamiast throw string.

Przykład:

try {
    0++;
} catch (e) {
    var myStackTrace = e.stack || e.stacktrace || "";
}
Eli Gray
źródło
stacktrace nie działa w Operze. Nie mogę nawet znaleźć czegoś na ten temat.
NVI
@NV: Wygląda na to, że stacktrace nie zawiera błędów utworzonych przez użytkownika, więc powinieneś to zrobić: spróbuj {0 ++} catch (e) {myStackTrace = e.stack || e.stacktrace}
Eli Gray
7

To da ślad stosu (jako tablicę ciągów) dla współczesnych Chrome, Opera, Firefox i 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);
}

Stosowanie:

console.log(getStackTrace().join('\n'));

Wyklucza ze stosu własne wywołanie, a także tytuł „Błąd” używany przez Chrome i Firefox (ale nie IE).

Nie powinno to powodować awarii starszych przeglądarek, ale po prostu zwracać pustą tablicę. Jeśli potrzebujesz bardziej uniwersalnego rozwiązania, zajrzyj na stacktrace.js . Lista obsługiwanych przeglądarek jest naprawdę imponująca, ale moim zdaniem jest bardzo duża do tego małego zadania, do którego jest przeznaczona: 37 KB zminimalizowanego tekstu z uwzględnieniem wszystkich zależności.

Konstantin Smolianin
źródło
7

Aktualizacja odpowiedzi Eugene'a: ​​Obiekt błędu musi zostać zgłoszony, aby IE (określone wersje?) Wypełnił stackwłaściwość. Następujące powinny działać lepiej niż jego obecny przykład i powinny unikać powrotu undefinedw IE.

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

Uwaga 1: Tego rodzaju czynności należy wykonywać tylko podczas debugowania, a wyłączać na żywo, zwłaszcza jeśli są często wywoływane. Uwaga 2: To może nie działać we wszystkich przeglądarkach, ale wydaje się działać w FF i IE 11, co dobrze odpowiada moim potrzebom.

Patrick Seymour
źródło
6

jednym ze sposobów uzyskania prawdziwego śladu stosu w Firebug jest utworzenie prawdziwego błędu, takiego jak wywołanie niezdefiniowanej funkcji:

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

Lub użyj console.error()po nim throwinstrukcji, ponieważ console.error()pokazuje ślad stosu.

Miller Medeiros
źródło
4

Ten kod wypełniający działa w nowoczesnych przeglądarkach (2017) (IE11, Opera, Chrome, FireFox, Yandex):

printStackTrace: function () {
    var err = new Error();
    var stack = err.stack || /*old opera*/ err.stacktrace || ( /*IE11*/ console.trace ? console.trace() : "no stack info");
    return stack;
}

Inne odpowiedzi:

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

nie działa w IE 11!

Korzystanie z arguments.callee.caller - nie działa w trybie ścisłym w żadnej przeglądarce!

Petr Varyagin
źródło
3

W Google Chrome (wersja 19.0 i nowsze) po prostu zgłoszenie wyjątku działa idealnie. Na przykład:

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

pokaże ślad stosu na wyjściu konsoli przeglądarki:

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

Mam nadzieję, że to pomoże.

Rabih Kodeih
źródło
3

funkcjonować:

function print_call_stack(err) {
    var stack = err.stack;
    console.error(stack);
}

przypadek użycia:

     try{
         aaa.bbb;//error throw here
     }
     catch (err){
         print_call_stack(err); 
     }
Jaskey
źródło
2
<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>

ten skrypt pokaże błąd

Amir Buzo
źródło
2
function stacktrace(){
  return (new Error()).stack.split('\n').reverse().slice(0,-2).reverse().join('\n');
}
Denis Orłow
źródło
2
Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, jak i / lub dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi.
Kaczor Donald
1

Trochę późno na imprezę, ale oto inne rozwiązanie, które automatycznie wykrywa, czy arguments.callee jest dostępny, i używa nowego Error (). Stosu, jeśli nie. Testowane w Chrome, Safari i Firefox.

2 warianty - stackFN (n) daje nazwę funkcji n od bezpośredniego wywołującego, a stackArray () daje tablicę, stackArray () [0] jest bezpośrednim wywołującym.

Wypróbuj na 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();
niezsynchronizowane
źródło
1

Możesz skorzystać z tej biblioteki http://www.stacktracejs.com/ . To jest bardzo dobre

Z dokumentacji

Możesz również przekazać własny Błąd, aby uzyskać śledzenie stosu niedostępne w IE lub 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>
Doua Beri
źródło
Powiązane źródło https://rawgithub.com/stacktracejs/stacktrace.js/master/stacktrace.jsto stara wersja, najnowsza stabilna wersja ( https://raw.githubusercontent.com/stacktracejs/stacktrace.js/stable/stacktrace.js
zgodna z
1

Oto odpowiedź, która zapewnia maksymalną wydajność (IE 6+) i maksymalną zgodność. Kompatybilny z 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>" );
})();

Jack Giffin
źródło
0

Łatwiej jest uzyskać ślad stosu w Firefoksie niż w IE, ale zasadniczo oto, co chcesz zrobić:

Zawiń „problematyczny” fragment kodu w blok try / catch:

try {
    // some code that doesn't work
    var t = null;
    var n = t.not_a_value;
}
    catch(e) {
}

Jeśli sprawdzisz zawartość obiektu „error”, zawiera on następujące pola:

e.nazwa_pliku: plik źródłowy / strona, z której pochodzi problem e.lineNumber: numer wiersza w pliku / stronie, na której powstał problem e.message: prosty komunikat opisujący, jaki typ błędu miał miejsce e.name: typ błędu, który miał miejsce, w powyższym przykładzie powinna to być „TypeError” e.stack: Zawiera ślad stosu, który spowodował wyjątek

Mam nadzieję, że to ci pomoże.

Michał
źródło
1
Źle. Próbuje uchwycić swoje WŁASNE wyjątki. Jeśli wyrzuci „asdfg”, dostanie obiekt typu string, a nie obiekt wyjątku. Nie próbuje wychwycić wbudowanych wyjątków.
Ivan Vučica,
0

Musiałem zbadać niekończącą się rekurencję w smartgwt z IE11, więc aby zbadać głębiej, potrzebowałem śledzenia stosu. Problem polegał na tym, że nie mogłem korzystać z konsoli programisty, ponieważ w ten sposób odtwarzanie było trudniejsze.
Użyj następujących metod w metodzie javascript:

try{ null.toString(); } catch(e) { alert(e.stack); }
kirilv
źródło
alert ((nowy Błąd ()). stos);
rich remer
0

Wow - od 6 lat nie widzę ani jednej osoby, co sugeruje, że najpierw sprawdzamy, czy stackjest dostępna przed użyciem! Najgorszą rzeczą, jaką możesz zrobić w module obsługi błędów, jest zgłoszenie błędu z powodu wywołania czegoś, co nie istnieje.

Jak powiedzieli inni, chociaż stackjest teraz w większości bezpieczny w użyciu, nie jest obsługiwany w IE9 ani wcześniejszych.

Rejestruję moje nieoczekiwane błędy, a śledzenie stosu jest bardzo istotne. Aby uzyskać maksymalne wsparcie, najpierw sprawdzam, czy Error.prototype.stackistnieje i czy jest funkcją. Jeśli tak, to jest bezpieczny w użyciu 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)
            {

            }
        };

Edycja: Wygląda na to, że ponieważ stackjest to właściwość, a nie metoda, można ją bezpiecznie wywołać nawet w starszych przeglądarkach. Nadal jestem zdezorientowany, ponieważ byłem całkiem pewien, że sprawdzanie Error.prototypedziałało dla mnie wcześniej, a teraz nie - więc nie jestem pewien, co się dzieje.

Simon_Weaver
źródło
0

Używanie console.error(e.stack)przeglądarki Firefox pokazuje tylko dziennik stosu w dziennikach, Chrome wyświetla również komunikat. Może to być zła niespodzianka, jeśli wiadomość zawiera istotne informacje. Zawsze loguj oba.

Christophe Roussy
źródło
0

Spróbuj

throw new Error('some error here')

Działa to całkiem dobrze w przypadku chrome:

wprowadź opis zdjęcia tutaj

Anthony Zhan
źródło