ฉันจะได้รับการติดตาม JavaScript แบบกองซ้อนได้อย่างไรเมื่อฉันส่งข้อยกเว้น?


519

หากฉันโยนข้อยกเว้น 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, ,barbar


1
อาจเป็นไปได้ที่ซ้ำกันของการติดตามสแต็กข้อยกเว้น Javascript
ripper234

ข้อผิดพลาดยังคงเปิดอยู่ในตัวติดตามบั๊ก Firebug ตั้งแต่ปี 2008: code.google.com/p/fbug/issues/detail?id=1260 - ติดดาว!
มิลเลอร์ Medeiros

13
คำตอบควรเป็น "โยนข้อผิดพลาดใหม่ ('arrrgh');" ดูหน้านี้เป็นลายลักษณ์อักษรอย่างดี: devthought.com/2011/12/22/a-string-is-not-an-error
ลูกเต๋าที่สง่างาม

1
(2013) ตอนนี้คุณจะได้รับร่องรอยสแต็คใน Firebug บน Firefox ถึงแม้ว่ามันจะเป็นเพียงและพวกเขาดูเหมือนเดียวกันเช่นเดียวกับthrow 'arrrgh'; throw new Error('arrrgh');อย่างไรก็ตามโปรแกรมดีบั๊กของ Chrome ยังคงมีความต้องการthrow new Error('arrrgh');ตามที่ระบุไว้ (แต่ Chrome ดูเหมือนจะให้รายละเอียดเพิ่มเติมอย่างละเอียด)
user56reinstatemonica8

26
@ChetanSastry ฉัน googled สำหรับ 'javascript stack trace' และนี่เป็นผลลัพธ์แรก
David Sykes

คำตอบ:


756

แก้ไข 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);
}

11
ฉันไม่แน่ใจว่าทำไมสิ่งนี้ถึงไม่ได้รับการโหวตมากขึ้นคำตอบอื่น ๆ ไม่ได้ผลดีสำหรับฉัน BTW ตรวจสอบให้แน่ใจว่าจะไม่ถืออาร์กิวเมนต์เป็นอาร์เรย์ (ตัวอย่างข้อมูลอัปเดตที่นี่: gist.github.com/965603 )
ripper234

1
ไม่ทำงานใน chrome, tacktrace (): [ข้อยกเว้น: TypeError: Object # <Object> ไม่มีเมธอด
hetaoblog

3
ดูความคิดเห็นเกี่ยวกับคำถามเดิม: คุณไม่จำเป็นต้องใช้รหัสที่กำหนดเองเพียงใช้ "โยนข้อผิดพลาดใหม่ ('arrrgh')"
Joshua Richardson

16
Error.stack จะไม่ได้กำหนดใน IE จะทำงานเฉพาะในโครเมี่ยมและ Mozilla Firefox
ฟิลิปป์ Munin

4
โปรดทราบว่าcallerขณะนี้เลิกใช้แล้วและcalleeถูกลบออกจากโหมดเข้มงวด ES5 นี่คือเหตุผลที่stackoverflow.com/questions/103598/…
PhilT

187

โปรดทราบว่า Chromium / chrome (เบราว์เซอร์อื่นที่ใช้ V8) และ Firefox มีอินเทอร์เฟซที่สะดวกในการรับสแต็คผ่านคุณสมบัติสแต็กบนวัตถุข้อผิดพลาด

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

มันใช้สำหรับข้อยกเว้นฐานเช่นเดียวกับสิ่งที่คุณโยนตัวเอง (ถือว่าคุณใช้คลาส Error ซึ่งเป็นแนวปฏิบัติที่ดีอยู่แล้ว)

ดูรายละเอียดเกี่ยวกับเอกสาร V8


12
Firefox รองรับ.stackคุณสมบัติเช่นกัน
kennytm

2
ฉันหวังว่าฉันจะโหวตได้ 100 ครั้ง! ขอบคุณโจเซลีน มันช่วยได้มากจริงๆ
safrazik

1
คุณยังสามารถใช้console.error(e.stack);เพื่อให้ดูเหมือนเป็นข้อความแสดงข้อยกเว้นเริ่มต้น
Bruno Peres

80

ใน Firefox ดูเหมือนว่าคุณไม่จำเป็นต้องทิ้งข้อยกเว้น มันเพียงพอที่จะทำ

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

ใช้งานได้ในแอพมือถือ (สร้างโดยใช้ JQM) เช่นกัน
Samik R

ทำงานได้ใน Chromium เช่นกัน (รุ่น 43 อยู่ดี)
Andy Beverley

ใน Firefox 59 สิ่งนี้ไม่ทำงานเมื่อถูกเรียกผ่านwindow.onerrorมันจะแสดงสแต็กที่ว่างเปล่าเกือบมีเพียงonerrorฟังก์ชั่น
Code4R7

ยิ่งไปกว่านั้นคุณสามารถทำได้: console.log(new Error().stack)> :(> :(> :(
Andrew

25

หากคุณมี firebug มีตัวเลือกข้อผิดพลาดทั้งหมดในแท็บสคริปต์ เมื่อสคริปต์เข้าสู่เบรกพอยต์ของคุณคุณสามารถดูที่หน้าต่างสแต็คของ firebug:

ภาพหน้าจอ


5
อืมดูเหมือนว่าจะไม่ทำงาน มันหยุดฉันในการดีบักเกอร์จากข้อผิดพลาดที่เกิดขึ้นจาก Javascript (เช่นข้อผิดพลาดตัวแปรที่ไม่ได้กำหนด) แต่เมื่อฉันโยนข้อยกเว้นของตัวเองฉันยังไม่ได้รับอะไรเลยยกเว้นข้อความ "Uncaught exception"
David Wolever

11

วิธีแก้ปัญหาที่ดี (และง่าย) ตามที่ระบุไว้ในความคิดเห็นเกี่ยวกับคำถามเดิมคือการใช้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.showInfoเป็นfalse) หรือปิดใช้งานการดีบักทั้งหมด (ตั้งค่าConsole.settings.debug.enabledเป็นfalse) เพื่อให้คุณไม่ต้องแสดงความคิดเห็นต่อคำสั่งการดีบักอีกครั้ง! เพียงแค่ปล่อยพวกเขาไว้และสิ่งนี้จะไม่ทำอะไรเลย


10

ฉันไม่คิดว่าจะมีสิ่งใดในตัวที่คุณสามารถใช้งานได้ แต่ฉันได้พบตัวอย่างมากมายของคนที่กลิ้งตัวเอง


อ่าขอบคุณ - ลิงค์แรกที่มีดูเหมือนว่ามันอาจจะทำ (แม้ว่าการขาดการสนับสนุนการเรียกซ้ำอาจทำให้มันใช้งานไม่ได้)
David Wolever

ใช่ฉันไม่เห็นสิ่งใดที่รองรับการเรียกซ้ำตัวเองในการมองแวบแรก ฉันอยากรู้ว่ามีวิธีแก้ปัญหาที่ดีหรือไม่
Mark Biek

1
ฉันคิดว่าลิงก์ที่สองควรสนับสนุนการเรียกซ้ำสำหรับ Firefox และ Opera เนื่องจากใช้การติดตามสแต็กข้อผิดพลาดมากกว่าการสร้างลิงก์ด้วยตนเองโดยใช้ตัวแปรอาร์กิวเมนต์ ฉันชอบที่จะได้ยินถ้าคุณพบโซลูชันข้ามเบราว์เซอร์สำหรับปัญหาการเรียกซ้ำ (บทความแรกเป็นของฉัน) :)
ช่วย

Helephant: ข้อที่สองจะไม่ทำงานที่นี่เพราะเมื่อฉันได้รับการยกเว้นมันเป็น "string" (เช่นไม่มี "e.stack"): foo = function () {throw "Arg"; } ลอง {foo (); } catch (e) {/ * typeof e == "string" * /} บางทีฉันอาจจะผิดหรือเปล่า? (เริ่มพูดจาโผงผางบังคับเกี่ยวกับวิธีการสอนแบบจาวาสคริปต์โง่ ... )
David Wolever

พยายามโยนวัตถุ: throw { name: 'NameOfException', message: 'He's dead, Jim' }.
Aaron Digulla

7

คุณสามารถเข้าถึงคุณสมบัติstack( stacktraceใน Opera) ของErrorอินสแตนซ์แม้ว่าคุณจะโยนมัน สิ่งที่เป็นคุณต้องให้แน่ใจว่าคุณใช้throw new Error(string)(อย่าลืมใหม่throw stringแทน

ตัวอย่าง:

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

stacktrace ไม่ทำงานใน Opera ฉันไม่สามารถหาอะไรเกี่ยวกับมันได้
NVI

@NV: ดูเหมือนว่า stacktrace ไม่ได้อยู่ในข้อผิดพลาดที่ผู้ใช้สร้างขึ้นดังนั้นคุณควรทำดังนี้: ลอง {0 ++} catch (e) {myStackTrace = e.stack || e.stacktrace}
Eli Gray


7

สิ่งนี้จะให้การติดตามสแต็ก (เป็นอาร์เรย์ของสตริง) สำหรับ 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 รวมถึงการขึ้นต่อกันทั้งหมด


7

การอัปเดตคำตอบของ Eugene: ต้องโยนวัตถุข้อผิดพลาดเพื่อให้ IE (รุ่นที่เฉพาะเจาะจง?) เพื่อเติมstackคุณสมบัติ ต่อไปนี้ควรทำงานได้ดีกว่าตัวอย่างปัจจุบันของเขาและควรหลีกเลี่ยงการส่งคืนundefinedเมื่ออยู่ใน IE

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

หมายเหตุ 1: สิ่งเหล่านี้ควรทำเมื่อทำการดีบั๊กและปิดการใช้งานเมื่อใช้งานจริงโดยเฉพาะถ้าโทรบ่อย หมายเหตุ 2: สิ่งนี้อาจไม่ทำงานในเบราว์เซอร์ทั้งหมด แต่ดูเหมือนว่าจะทำงานใน FF และ IE 11 ซึ่งเหมาะสมกับความต้องการของฉันได้ดี


6

วิธีหนึ่งในการรับการติดตามสแต็กจริงบน 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()แสดงการติดตามสแต็ก


4

รหัส polyfill นี้ทำงานในเบราว์เซอร์ที่ทันสมัย ​​(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;
}

คำตอบอื่น ๆ :

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

ไม่ทำงานใน IE 11!

ใช้arguments.callee.caller - ไม่ทำงานในโหมดเข้มงวดในเบราว์เซอร์ใด ๆ !


3

ใน 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

หวังว่าความช่วยเหลือนี้


3

ฟังก์ชั่น:

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

ใช้กรณี:

     try{
         aaa.bbb;//error throw here
     }
     catch (err){
         print_call_stack(err); 
     }

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>

สคริปต์นี้จะแสดงข้อผิดพลาด


2
function stacktrace(){
  return (new Error()).stack.split('\n').reverse().slice(0,-2).reverse().join('\n');
}

2
ในขณะที่รหัสนี้อาจตอบคำถามให้บริบทเพิ่มเติมเกี่ยวกับวิธีการและ / หรือทำไมมันแก้ปัญหาจะปรับปรุงค่าระยะยาวของคำตอบ
โดนัลด์ดั๊ก

1

ชนิดของสายไปปาร์ตี้ แต่นี่คือโซลูชันอื่นซึ่งตรวจหาอัตโนมัติถ้าอาร์กิวเมนต์.calleeพร้อมใช้งานและใช้ข้อผิดพลาดใหม่ () สแต็กถ้าไม่ใช่ ทดสอบในโครเมี่ยมซาฟารีและ 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

คุณสามารถใช้ห้องสมุดนี้http://www.stacktracejs.com/ มันดีมาก

จากเอกสาร

คุณสามารถส่งข้อผิดพลาดของคุณเองเพื่อรับ stacktrace ที่ไม่พร้อมใช้งานใน 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>

แหล่งที่เชื่อมโยงhttps://rawgithub.com/stacktracejs/stacktrace.js/master/stacktrace.jsเป็นรุ่นเก่ารุ่นเสถียรล่าสุด (จับคู่โค้ดขนาดสั้น) อยู่ที่นี่:https://raw.githubusercontent.com/stacktracejs/stacktrace.js/stable/stacktrace.js
Frederic Leitenberger

1

นี่คือคำตอบที่ให้ประสิทธิภาพสูงสุด (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>" );
})();


0

มันง่ายกว่าที่จะได้รับ stack stack บน Firefox มากกว่า IE แต่พื้นฐานนี่คือสิ่งที่คุณต้องการทำ:

ล้อมส่วนของโค้ด "ที่มีปัญหา" ไว้ในบล็อก try / catch:

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

หากคุณจะตรวจสอบเนื้อหาของวัตถุ "error" จะมีฟิลด์ดังต่อไปนี้:

e.fileName: ไฟล์ต้นฉบับ / หน้าที่มีปัญหามาจาก e.lineNumber: หมายเลขบรรทัดในไฟล์ / หน้าซึ่งปัญหาเกิดขึ้น e.message: ข้อความง่าย ๆ ที่อธิบายถึงประเภทของข้อผิดพลาดที่เกิดขึ้น e.name: ประเภท ข้อผิดพลาดที่เกิดขึ้นในตัวอย่างข้างต้นควรเป็น 'TypeError' e.stack: มีการติดตามสแต็กที่ทำให้เกิดข้อยกเว้น

ฉันหวังว่านี่จะช่วยคุณได้


1
ไม่ถูกต้อง. เขาพยายามจับข้อยกเว้นของตัวเอง ถ้าเขาพ่น "asdfg" เขาจะได้รับวัตถุสตริงไม่ใช่วัตถุยกเว้น เขาไม่ได้พยายามที่จะจับข้อยกเว้นในตัว
Ivan Vučica

0

ฉันต้องตรวจสอบการเรียกซ้ำแบบไม่มีที่สิ้นสุดใน smartgwt ด้วย IE11 ดังนั้นเพื่อที่จะตรวจสอบให้ลึกยิ่งขึ้นฉันต้องใช้การติดตามสแต็ก ปัญหาคือว่าฉันไม่สามารถใช้คอนโซล dev เพราะการทำซ้ำนั้นยากกว่า
ใช้สิ่งต่อไปนี้ในวิธี javascript:

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

alert ((ข้อผิดพลาดใหม่ ()). stack);
รวย remer

0

ว้าว - ฉันไม่เห็นคนคนเดียวใน 6 ปีแนะนำว่าเราตรวจสอบก่อนเพื่อดูว่า stackมีให้ก่อนใช้งานหรือไม่! สิ่งที่แย่ที่สุดที่คุณสามารถทำได้ในตัวจัดการข้อผิดพลาดคือการโยนข้อผิดพลาดเนื่องจากการเรียกสิ่งที่ไม่มีอยู่

อย่างที่คนอื่นพูดกัน stackส่วนใหญ่จะปลอดภัยที่จะใช้ตอนนี้มันไม่รองรับใน IE9 หรือเก่ากว่า

ฉันบันทึกข้อผิดพลาดที่ไม่คาดคิดและการติดตามสแต็กนั้นค่อนข้างสำคัญ เพื่อรองรับสูงสุดฉันก่อนตรวจสอบเพื่อดูว่า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งานได้สำหรับฉันมาก่อนและตอนนี้ก็ไม่ได้ดังนั้นฉันจึงไม่แน่ใจว่าเกิดอะไรขึ้น


0

การใช้console.error(e.stack)Firefox จะแสดงเฉพาะสแต็คเทรซในบันทึกเท่านั้น Chrome ยังแสดงข้อความ นี่อาจเป็นเรื่องแปลกใจหากข้อความนั้นมีข้อมูลที่สำคัญ บันทึกทั้งคู่เสมอ


0

เพียงแค่พยายามที่

throw new Error('some error here')

วิธีนี้ใช้งานได้ดีสำหรับโครเมี่ยม:

ป้อนคำอธิบายรูปภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.