2013-04-24 48 views
7

Khi tôi gặp lỗi trong ExtendScript, tôi muốn có thể ghi nhật ký ngăn xếp của nó. Dường như các lỗi không chứa dấu vết ngăn xếp trong ExtendScript, vì vậy tôi đang chơi xung quanh với ý tưởng thêm dấu vết ngăn xếp vào lỗi.Bắt dấu vết ngăn xếp của một lỗi trong ExtendScript

Cách duy nhất tôi biết để nhận dấu vết ngăn xếp là $.stack. Trường $.stack chứa dấu vết ngăn xếp hiện tại tại thời điểm bạn truy cập trường.

Nỗ lực đầu tiên của tôi là tạo đối tượng lỗi của riêng tôi bao gồm ngăn xếp. Đối tượng Error rất đặc biệt ở chỗ nó có thể nhận được dòng và tên tệp của mã đã tạo ra nó. Ví dụ,

try { 
    throw new Error("Houston, we have a problem."); 
} 
catch (e) { 
    $.writeln("Line: " + e.line); 
    $.writeln("File: " + e.fileName); 
    $.writeln("Message: " + e.message); 
} 

Sẽ in:

Line: 2 
File: ~/Desktop/Source1.jsx 
Message: Houston, we have a problem. 

Tôi không nghĩ rằng nó có thể tạo ra đối tượng của riêng bạn với khả năng này. Gần nhất tôi có thể nhận được là thế này:

function MyError(msg, file, line) { 
    this.message = msg; 
    this.fileName = file; 
    this.line = line; 
    this.stack = $.stack; 
} 

try { 
    throw new MyError("Houston, we have a problem.", $.fileName, $.line); 
} 
catch (e) { 
    $.writeln("Line: " + e.line); 
    $.writeln("File: " + e.fileName); 
    $.writeln("Message: " + e.message); 
    $.writeln("Stack: " + e.stack); 
} 

nào in:

Line: 9 
File: ~/Desktop/Source2.jsx 
Message: Houston, we have a problem. 
Stack: [Source3.jsx] 
MyError("Houston, we have a p"...,"~/Desktop/Source2.js"...,9) 

Ở đây chúng ta có thể thấy rằng tôi là tạo ra đối tượng lỗi của riêng tôi và rõ ràng đi qua nó dòng và tên file (kể từ MyError không thể hình dung ra điều đó). Tôi cũng đã bao gồm ngăn xếp hiện tại khi lỗi được tạo.

Điều này hoạt động tốt khi tôi gọi đối tượng lỗi của riêng mình, nhưng nó không hoạt động khi mã khác gọi đối tượng Lỗi thông thường hoặc khi lỗi được tạo tự động (ví dụ: truy cập bất hợp pháp). Tôi muốn có thể nhận được dấu vết ngăn xếp của bất kỳ lỗi nào, bất kể nó được tạo ra như thế nào.

Các cách tiếp cận khác có thể là sửa đổi hàm xây dựng Error, sửa đổi nguyên mẫu Error hoặc thay thế hoàn toàn đối tượng Error. Tôi đã không thể có được bất kỳ cách tiếp cận nào để làm việc.

Một ý tưởng khác là đặt khối catch vào mọi phương thức mã của tôi và thêm ngăn xếp hiện tại vào lỗi nếu nó chưa có. Tôi muốn tránh tùy chọn này nếu có thể.

Tôi hết ý tưởng. Có cách nào để có được dấu vết ngăn xếp của các lỗi?

+0

Tôi thực sự quan tâm nếu bạn làm việc gì đó. Vấn đề lớn nhất của tôi là ngay khi tôi biên dịch sang định dạng jsxbin, tôi không nhận được gì hữu ích từ các lỗi. Tôi đã đi con đường của một số lượng đáng kinh ngạc của khai thác gỗ xảy ra vì vậy tôi có thể gỡ lỗi từ đó. –

+0

Personnaly Tôi woudl'nt sử dụng $ .write hoặc $ .writeln hướng dẫn. Trước hết, họ sẽ mang lại Advance Toolkit ExtendScript nếu không mở yer. Điều đó có thể gây nhầm lẫn cho người dùng cuối nếu họ không cảnh báo. Ngoài ra nó có thể được thực sự thực sự chậm đặc biệt là các vòng bên trong. Tôi thích viết tệp nhật ký vào đĩa. Tôi có công thức riêng của tôi nhưng bạn có thể tận dụng lợi thế của lib này: http: //creative-scripts.com/logging-with-a-smile/ – Loic

Trả lời

1

Nó không hoàn hảo, nhưng tôi tìm thấy một giải pháp một phần.

Sự kiện 1: Error.prototype là một đối tượng Lỗi.

Sự kiện 2: Phương pháp Error.prototype.toString được gọi bất cứ khi nào lỗi được tạo.

Sự kiện 3: Trường Error.prototype.toString có thể được sửa đổi.

Phương pháp đó thường chỉ trả về chuỗi "Lỗi", vì vậy chúng tôi có thể thay thế bằng phương pháp riêng của chúng tôi lưu trữ ngăn xếp và sau đó trả về chuỗi "Lỗi".

Error.prototype.toString = function() { 
    if (typeof this.stack === "undefined" || this.stack === null) { 
     this.stack = "placeholder"; 
     // The previous line is needed because the next line may indirectly call this method. 
     this.stack = $.stack; 
    } 
    return "Error"; 
} 

try { 
    throw new Error("Houston, we have a problem."); 
} 
catch (e) { 
    $.writeln("Line: " + e.line); 
    $.writeln("File: " + e.fileName); 
    $.writeln("Message: " + e.message); 
    $.writeln("Stack: " + e.stack); 
} 

Kết quả:

Line: 11 
File: ~/Desktop/Source10.jsx 
Message: Houston, we have a problem. 
Stack: [Source10.jsx] 
toString() 

Nó hoạt động! Vấn đề duy nhất là lỗi tự động.

Error.prototype.toString = function() { 
    if (typeof this.stack === "undefined" || this.stack === null) { 
     this.stack = "placeholder"; 
     // The previous line is needed because the next line may indirectly call this method. 
     this.stack = $.stack; 
    } 
    return "Error"; 
} 

try { 
    var foo = null; 
    foo.bar; 
} 
catch (e) { 
    $.writeln("Line: " + e.line); 
    $.writeln("File: " + e.fileName); 
    $.writeln("Message: " + e.message); 
    $.writeln("Stack: " + e.stack); 
} 

Kết quả:

Line: 12 
File: ~/Desktop/Source12.jsx 
Message: null is not an object 
Stack: undefined 

Vì vậy, nó không hoạt động trên tất cả các lỗi, nhưng tiến trình của nó.

2

Tôi đã đưa ra một giải pháp khác, mặc dù điều này yêu cầu bạn phải thay đổi một số mã của mình. Thay vì kêu gọi các phương pháp như bình thường:

myObject.myMethod1("Hello", "world"); 

Bạn sẽ cần phải chuyển sang phương pháp kêu gọi như thế này:

myObject.do("myMethod1", "Hello", "world"); 

Dưới đây là một ví dụ hoàn chỉnh về cách hoạt động:

Object.prototype.do = function stackHelper() { 
    // Convert the arguments into an array. 
    var argumentArray = Array.prototype.slice.call(arguments); 
    // Remove the first argument, which is the function's name. 
    var functionString = argumentArray.shift(); 
    try { 
     this[functionString].apply(this, argumentArray); 
    } 
    catch (e) { 
     if (typeof e.stack === "undefined" || e.stack === null) { 
      e.stack = $.stack; 
     } 
     throw e; 
    } 
}; 

var myObject = { 
    myMethod1: function myMethod1(myArg1, myArg2){ 
     this.do("myMethod2", myArg1, myArg2); 
    }, 

    myMethod2: function myMethod2(myArg1, myArg2){ 
     this.do("myMethod3", myArg1, myArg2); 
    }, 

    myMethod3: function myMethod3(myArg1, myArg2){ 
     $.writeln(myArg1 + ", " + myArg2 + "!"); 
     var foo = null; 
     foo.bar; // Throws an error. 
    }, 
}; 

try { 
    myObject.do("myMethod1", "Hello", "world"); 
} 
catch (e) { 
    $.writeln("Stack: " + e.stack); 
} 

Các sản lượng trông giống như sau:

Hello, world! 
Stack: [do.jsx] 
stackHelper("myMethod1","Hello","world") 
myMethod1("Hello","world") 
stackHelper("myMethod2","Hello","world") 
myMethod2("Hello","world") 
stackHelper("myMethod3","Hello","world") 

Nó không phải là một giải pháp tuyệt vời, nhưng ít nhất nó hoạt động trên tất cả các lỗi.

0

Nếu bạn chỉ cần hiển thị thông báo tùy chỉnh, tôi đã viết mã này. Tôi nghĩ rằng giải quyết, ... đối với tôi nó là ok.

try 
{ 
    app.selection[0].contents = 1 
} 
catch (myError) 
{ 
    alert(myError.number); // For check the number error 
    if (myError.number == 30477) 
    { 
     alert("Mensagem Edu\n" + "Line: " + myError.line + "\n" + "File: " + myError.fileName + "\n" + "Message: " + myError.message + "\n" + "Stack: " + myError.stack); 
     exit(); 
    } 
    else (myError); 
    {} 
    exit(); 
} 
+0

Có ai nhận được bất cứ điều gì khác hơn là 'undefined' cho' myError.stack', mà điểm của câu hỏi của OP là gì? –

1

Theo như tôi biết bạn không thể sửa đổi [Mã gốc] của Error.prototype.toString-chức năng. Vì vậy, tôi đã đưa ra giải pháp này:

function ReturnCustomErrorString(e, additionalMessage) 
{ 
    try { 
     var errorString = e.toString(); 
     errorString = errorString.concat("\n", "additionalMessage: " + additionalMessage + "\n", "file: " + e.fileName + "\n", "line: " + e.line + "\n", "stack-trace: \n" + $.stack); 
     return errorString; 
    } 
    catch (e) { 
     alert("Error in : " + ReturnCustomErrorString.name + "(...)\n" + e); 
     exit(); 
    } 
} 

Cách sử dụng:

try { 
    // code that does throw an error 
} catch (e) { 
    alert(ReturnCustomErrorString(e)); 
} 

Trước khi tôi viết hàm này tôi thường làm một cái gì đó như thế này trong khối catch:

alert(e); 

Bây giờ tôi đang làm alert(ReturnCustomErrorString(e));, nhưng tôi nhận được nhiều thông tin hữu ích hơn. Vì vậy, tại thời điểm này tôi nghĩ rằng giải pháp này là khá tốt.

Các vấn đề liên quan