2011-02-02 4 views
24

Làm thế nào Javascript có thể sao chép bốn phần try - catch - else - finally mô hình thực thi mà các ngôn ngữ khác hỗ trợ?Javascript thử ... bắt ... khác ... cuối cùng như Python, Java, Ruby, v.v.

Tóm tắt ngắn gọn rõ ràng là từ Python 2.5 what's new. Về Javascript:

// XXX THIS EXAMPLE IS A SYNTAX ERROR 
try { 
    // Protected-block 
} catch(e) { 
    // Handler-block 
} else { 
    // Else-block 
} finally { 
    // Final-block 
} 

Các mã trong bảo vệ khối được thực thi. Nếu mã ném một ngoại lệ, Bộ xử lý chặn được thực thi; Nếu không có ngoại lệ nào được ném, Các khối khác được thực hiện.

Không có vấn đề gì xảy ra trước đó, Khối cuối cùng được thực hiện khi khối mã hoàn tất và mọi ngoại lệ được ném được xử lý. Ngay cả khi có lỗi trong số Bộ xử lý chặn hoặc Loại khác chặn và ngoại lệ mới được nêu ra, mã trong Khối cuối cùng vẫn chạy.

Lưu ý rằng cắt Else-block và dán vào cuối bảo vệ khốisai. Nếu xảy ra lỗi trong Loại khác chặn, nó không được được xử lý bởi Bộ xử lý chặn.

Trả lời

20

Mở rộng ý tưởng của JHS một chút, toàn bộ khái niệm có thể được đặt bên trong một hàm, để cung cấp nhiều hơn khả năng đọc:

var try_catch_else_finally = function(protected_code, handler_code, else_code, finally_code) { 
    try { 
    var success = true; 
    try { 
     protected_code(); 
    } catch(e) { 
     success = false; 
     handler_code({"exception_was": e}); 
    } 
    if(success) { 
     else_code(); 
    } 
    } finally { 
    finally_code(); 
    } 
}; 

Sau đó, chúng ta có thể sử dụng nó như thế này (rất giống với cách python):

try_catch_else_finally(function() { 
    // protected block 
}, function() { 
    // handler block 
}, function() { 
    // else block 
}, function() { 
    // final-block 
}); 
+0

Hoàn toàn. Tôi đã nghĩ đến việc làm một mô-đun NPM nhanh chóng để làm điều này. Tôi bỏ điều này ra khỏi câu trả lời của tôi bởi vì bạn phải cẩn thận vì giá trị 'this' sẽ thay đổi so với' try' lồng nhau đơn giản. Tuy nhiên ví dụ thứ hai của tôi cũng có lỗi đó. – JasonSmith

+0

Phải. Chúng tôi có thể muốn ràng buộc 'điều này' của người gọi đến bốn cuộc gọi lại. Hãy gọi nó là một bài tập cho người đọc;) – Jakob

+0

Chỉ cần xảy ra trở lại trên này. Lưu ý, trong các phiên bản JavaScript mới hơn, ký pháp "mũi tên chất béo" làm cho cú pháp thậm chí dễ đọc hơn. – JasonSmith

7

Javascript không có cú pháp để hỗ trợ trường hợp không có ngoại lệ. Cách giải quyết tốt nhất là lồng try báo cáo, tương tự như kỹ thuật "di sản" từ PEP 341

// A pretty-good try/catch/else/finally implementation. 
try { 
    var success = true; 
    try { 
    protected_code(); 
    } catch(e) { 
    success = false; 
    handler_code({"exception_was": e}); 
    } 
    if(success) { 
    else_code(); 
    } 
} finally { 
    this_always_runs(); 
} 

Bên cạnh khả năng đọc, vấn đề duy nhất là biến success. Nếu protected_code bộ window.success = false, điều này sẽ không hoạt động. Một cách dễ đọc hơn nhưng an toàn hơn sử dụng một chức năng không gian tên:

// A try/catch/else/finally implementation without changing variable bindings. 
try { 
    (function() { 
    var success = true; 
    try { 
     protected_code(); 
    } catch(e) { 
     success = false; 
     handler_code({"exception_was": e}); 
    } 
    if(success) { 
     else_code(); 
    } 
    })(); 
} finally { 
    this_always_runs(); 
} 
+0

cho ví dụ đầu tiên - bạn luôn có thể sử dụng Boolean mới() đúng/sai thay vì thành công = false | đúng - new Boolean() tạo ra đối tượng boolean mà khi so sánh với sự tồn tại trả về true trong mâu thuẫn với nghĩa đen giả mà khi được chọn cho sự tồn tại sẽ trả về false –

21

tôi biết điều này là cũ, nhưng đây là một tinh khiết giải pháp cú pháp, whic h tôi nghĩ là cách thích hợp để đi:

try { 
    // Protected-block 
    try { 
     // Else-block 
    } catch (e) { 
     // Else-handler-block 
    } 
} catch(e) { 
    // Handler-block 
} finally { 
    // Final-block 
} 

Các mã trong bảo vệ khối được thực thi. Nếu mã ném lỗi, Bộ xử lý chặn được thực thi; Nếu không có lỗi nào được ném, Các khối khác được thực hiện.

Không có vấn đề gì xảy ra trước đó, Khối cuối cùng được thực hiện khi khối mã hoàn tất và mọi lỗi được xử lý.Ngay cả khi có lỗi trong Bộ xử lý chặn hoặc Loại khác chặn, mã trong Khối cuối cùng vẫn chạy.

Nếu một lỗi được ném trong Else-block nó là không xử lý bởi các Handler-block nhưng thay vào đó bằng những Else-handler-block

Và nếu bạn biết rằng Else-block sẽ không ném:

try { 
    // Protected-block 
    // Else-block 
} catch(e) { 
    // Handler-block 
} finally { 
    // Final-block 
} 

đạo đức của câu chuyện, đừng ngại để thụt;)

+0

Đẹp và sạch sẽ, không gây thêm sự phức tạp hoặc phụ thuộc. Tôi thích giải pháp này. –

+1

Tốt hơn nhiều so với việc thêm biến 'success' ... _unless_ bạn muốn bất kỳ lỗi nào được nêu trong khối' else' để bong bóng lên và _not_ bị chặn bởi khối xử lý chính, đó là cú pháp Python cho phép. Nếu đó là những gì bạn cần, tôi không thấy bất kỳ cách nào mà không có một số biến 'success'. – doctaphred

+1

Tuyệt vời. Tôi đã thực hiện phần này của http://www.transcrypt.org. –

4

Tôi biết câu hỏi là cũ và câu trả lời đã được đưa ra nhưng tôi nghĩ rằng câu trả lời của tôi là đơn giản nhất để có được một "khác" trong javascripts try-catch-block.

var error = null; 
try { 
    /*Protected-block*/ 
} catch (catchedError) { 
    error = catchedError; //necessary to make it available in finally-block 
} finally { 
    if (error) { 
     /*Handler-block*/ 
     /*e.g. console.log('error: ' + error.message);*/ 
    } else { 
     /*Else-block*/ 
    } 
    /*Final-block*/ 
}