Как я могу получить трассировку стека JavaScript при выдаче исключения? - PullRequest
455 голосов
/ 26 февраля 2009

Если я сам сгенерирую исключение JavaScript (например, throw "AArrggg"), как я могу получить трассировку стека (в Firebug или иным способом)? Прямо сейчас я просто получаю сообщение.

edit : Как много людей из нижеприведенного, опубликовали, возможно получить трассировку стека для исключения JavaScript , но я хочу получить трассировку стека для my исключений. Например:

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

Когда вызывается foo, я хочу получить трассировку стека, которая включает вызовы foo, bar, bar.

Ответы [ 24 ]

6 голосов
/ 13 марта 2015

Обновление ответа Юджина: объект ошибки должен быть брошен, чтобы IE (конкретные версии?) Заполнил свойство stack. Следующее должно работать лучше, чем его текущий пример, и не должно возвращать undefined в IE.

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

Примечание 1: Подобные действия следует выполнять только при отладке и отключать при работе, особенно при частом вызове. Примечание 2: Это может работать не во всех браузерах, но, похоже, работает в FF и IE 11, что вполне соответствует моим потребностям.

3 голосов
/ 08 июня 2012

В Google Chrome (версия 19.0 и более поздних) просто выбрасывание исключения работает отлично. Например:

/* 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

Надеюсь, эта помощь.

2 голосов
/ 13 августа 2017

Этот полизаполненный код работает в современных (2017 г.) браузерах (IE11, Opera, Chrome, FireFox, Яндекс):

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 - не работает в строгом режиме в любом браузере!

2 голосов
/ 30 октября 2015
<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>

этот скрипт покажет ошибку

2 голосов
/ 23 марта 2016

функция:

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

вариант использования:

     try{
         aaa.bbb;//error throw here
     }
     catch (err){
         print_call_stack(err); 
     }
1 голос
/ 05 апреля 2017

Вот ответ, который дает вам максимальную производительность (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( "" + stacktrace( false ) + "
"); }) ();
1 голос
/ 17 марта 2017
function stacktrace(){
  return (new Error()).stack.split('\n').reverse().slice(0,-2).reverse().join('\n');
}
1 голос
/ 13 июля 2014

В некотором роде поздно, но здесь есть другое решение, которое автоматически определяет , если arguments.callee доступен, и использует новый Error (). Stack, если нет. Протестировано в Chrome, 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();
1 голос
/ 22 октября 2014

Вы можете использовать эту библиотеку 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>
0 голосов
/ 15 октября 2014

Мне пришлось исследовать бесконечную рекурсию в smartgwt с IE11, поэтому для более глубокого исследования мне понадобилась трассировка стека. Проблема заключалась в том, что я не мог использовать консоль разработчика, потому что воспроизведение было сложнее.
Используйте следующее в методе javascript:

try{ null.toString(); } catch(e) { alert(e.stack); }
...