Try catch JavaScript là gì

Xử lý lỗi với try/catch trong JavaScript

Lỗi là gần như không thể tránh khỏi trong lập trình nói chung và các chương trình JavaScript nói riêng. Lỗi có thể là lỗi coding do lập trình viên gây ra, lỗi do input sai và cả những lỗi không lường trước được. Thông thường trong JavaScript, nếu có lỗi, một vài điều có thể xảy ra:

  • Trình duyệt sẽ lặng lẽ [silently] tự động báo lỗi của mã JavaScript xung quanh nơi xảy ra lỗi không được thực thi. Chúng ta có thể nhấn phím F12 để xem những thông báo lỗi này.
  • Hoặc trình duyệt sẽ tạo ra các cửa sổ pop up gây phiền nhiễu cho người dùng để thông báo rằng đã xảy ra lỗi.

Nhưng với những kiểu thông báo trên đều không phải là tùy chọn lý tưởng, là một nhà phát triển JavaScript, chúng ta cần dự đoán các lỗi và xử lý chúng một cách hiệu quả. Điều này cuối cùng sẽ giúp bạn tạo ra các chương trình mạnh mẽ, đáng tin cậy và hiệu quả. Một cách đơn giản để xử lý lỗi là thông qua câu lệnh trycatchfinally

Nội dung chính:
  1. Khối lệnh try/catch/finally
  2. Đặc điểm của khối lệnh finally
  3. Câu lệnh throw
  4. Đối tượng error
  5. Khối lệnh try/catch/finally có thể được lồng [nested] vào nhau
1. Khối lệnh try/catch/finally

1. Khối lệnh try/catch/finally

Trong block try cho dù chứa một hoặc nhiều câu lệnh cũng đều phải đặt trong cặp dấu ngoặc nhọn {}. Theo sau đó bắt buộc phải có ít nhất block lệnh của catch hoặc block lệnh của finally. Do đó, sẽ có 3 dạng [forms] của câu lệnh try:

  1. trycatch
  2. tryfinally
  3. trycatchfinally

Cú pháp:

try { Các lệnh thực thi } catch[err] { Các lệnh xử lý lỗi [handle errors] } finally { Các lệnh ở đây sẽ luôn được thực hiện bất kể kết quả của try / catch }

Cách thức hoạt động:

  • Đầu tiên sẽ thực thi các lệnh của khối try.
  • Sau khi thực thi các lệnh của khối try. Nếu không có lỗi thì khối catch sẽ được bỏ qua, ngược lại nếu có lỗi thì các lệnh xử lý lỗi ở khối catch sẽ được thực thi.
  • Dù có lỗi hay không có lỗi thì các lệnh của khối finally luôn được thực thi.

Trường hợp chương trình có lỗi: nếu có xử lý lỗi với try/catch thì chương trình vẫn được thực hiện đến cuối cùng. Nếu không có try/catch thì chương trình sẽ stop ngay tại dòng gây ra lỗi.

Ví dụ sau minh họa lỗi gọi hàm chưa được định nghĩa:

Trường hợp không có try/catch:function myFunction[] { welcome["Welcome guest!"]; // Vì phát sinh lỗi ở đây, nên chương trình sẽ stop tại dòng này, // mà không tiếp tục thực thi các xử lý bên dưới. document.getElementById["message"].innerHTML = "Minh Hoàng Blog | minhhn.com"; }Try it »
Trường hợp có try/catch:function myFunction[] { try { welcome["Welcome guest!"]; } catch[err] { document.getElementById["err"].innerHTML = "Lỗi gọi hàm chưa được định nghĩa!!!"; } // Vì đã có xử lý lỗi, nên dòng này vẫn được thực thi document.getElementById["message"].innerHTML = "Minh Hoàng Blog | minhhn.com"; }Try it »
Tương đương với try/catch/finally:function myFunction[] { try { welcome["Welcome guest!"]; } catch[err] { document.getElementById["err"].innerHTML = "Lỗi gọi hàm chưa được định nghĩa!!!"; } finally { document.getElementById["message"].innerHTML = "Minh Hoàng Blog | minhhn.com"; } }Try it »
2. Đặc điểm của khối lệnh finally

2. Đặc điểm của khối lệnh finally

Ngoài đặc điểm: sau khi thực thi các lệnh ở khối try dù có lỗi hay không có lỗi thì các lệnh của khối finally luôn được thực thi [như ví dụ ], thì finally còn một đặc điểm khác khá đặc biệt mà chúng ta sẽ xét ngay sau đây.

Các bạn có thể thấy ví dụ và cho ra một kết quả như nhau, vậy chúng ta cần finally để làm gì? Giả sử bạn viết một hàm để trả về kết quả tính toán nào đó, nhưng sau lệnh return bạn còn muốn thực hiện xử lý abc, xyz, nữa trước khi kết thúc hàm, chẳng hạn như close file hay dọn dẹp rác hủy các object đã khởi tạo,
Khi đó, nếu bạn đặt các xử lý abc, xyz, này vào trong khối finally, thì dù có đặt sau lệnh return, các xử lý đó vẫn được thực thi.

Để minh họa cho điều này, chúng ta sẽ quay lại với hai ví dụ và có sử dụng lệnh return:

Không có finally:function myFunction[] { try { welcome["Welcome guest!"]; } catch[err] { document.getElementById["err"].innerHTML = "Lỗi gọi hàm chưa được định nghĩa!!!"; return; } // Vì đã return; ở trên, nên các xử lý phía dưới sẽ không được thực thi document.getElementById["message"].innerHTML = "Minh Hoàng Blog | minhhn.com"; }Try it »
Có finally:function myFunction[] { try { welcome["Welcome guest!"]; } catch[err] { document.getElementById["err"].innerHTML = "Lỗi gọi hàm chưa được định nghĩa!!!"; return; } finally { // Mặc dù đã return; nhưng khối lệnh finally vẫn được thực thi document.getElementById["message"].innerHTML = "Minh Hoàng Blog | minhhn.com"; } }Try it »
3. Câu lệnh throw

3. Câu lệnh throw

Câu lệnh throw cho phép bạn tạo ra một thông báo lỗi riêng tùy ý [custom error].

Về mặt kỹ thuật bạn có thể ném ra một ngoại lệ [exception] [throw ra một error]. Ngoại lệ có thể là một chuỗi JavaScript, một số, một boolean hoặc một đối tượng:

throw "Số quá lớn"; // throw ra một chuỗi throw 500; // throw ra môt số

Nếu bạn sử dụng throw cùng với trycatch, bạn có thể kiểm soát luồng chương trình và tạo các thông báo lỗi tùy chỉnh:

Ví dụ:function myFunction[] { var message, x; message = document.getElementById["msg"]; message.innerHTML = ""; x = document.getElementById["number"].value; try { if[x == ""] throw "is empty"; if[isNaN[x]] throw "is not a number"; x = Number[x]; if[x > 10] throw "is too high"; if[x < 5] throw "is too low"; } catch[err] { message.innerHTML = "Error: " + err + "."; } finally { // Lúc nào thực hiện xong cũng reset giá trị input document.getElementById["number"].value = ""; } }Try it »
4. Đối tượng error

4. Đối tượng error

JavaScript có một error object được xây dựng để cung cấp thông tin lỗi khi xảy ra lỗi.

Error object có hai thuộc tính hữu ích là: namemessage.

PropertyDescription
nameThiết lập [set] hoặc return tên của lỗi [error name].
messageThiết lập [set] hoặc return một chuỗi thông báo lỗi [error message].
Ví dụ:try { blogMinhHoang; // error, variable is not defined! } catch[err] { document.getElementById["demo"].innerHTML = "err: " + err + "err.name: " + err.name + "err.message: " + err.message; }Try it »
Giá trị của thuộc tính error name

Thuộc tính error name có 6 giá trị khác nhau có thể được return:

Error NameDescription
EvalErrorĐã xảy ra lỗi trong hàm eval[].
RangeErrorĐã xảy ra lỗi một số ngoài phạm vi.
ReferenceErrorĐã xảy ra lỗi tham chiếu không hợp lệ.
SyntaxErrorĐã xảy ra lỗi cú pháp.
TypeErrorĐã xảy ra lỗi type.
URIErrorĐã xảy ra lỗi trong encodeURI[].
#1. Eval Error

EvalError chỉ ra một lỗi trong hàm eval[].

Các phiên bản JavaScript mới không ném [throw] ra bất kỳ EvalError nào. Sử dụng SyntaxError để thay thế.

#2. Range Error

Một lỗi RangeError được ném [throw] ra nếu bạn sử dụng một số nằm ngoài phạm vi giá trị hợp lệ.

Ví dụ: Bạn không thể set một số có tổng các chữ số là 500.

Ví dụ:var num = 1; try { num.toPrecision[500]; // Một số không thể có 500 chữ số có nghĩa } catch[err] { document.getElementById["demo"].innerHTML = err.name; }Try it »

Xem thêm về hàm toPrecision[] ở bài viết: Thuộc tính và phương thức của đối tượng JavaScript Number.

#3. Reference Error

Một lỗi ReferenceError được ném [throw] ra nếu bạn sử dụng [tham chiếu] một biến chưa được khai báo:

Ví dụ:var x; try { x = y + 1; // y không thể được tham chiếu [không thể được sử dụng] } catch[err] { document.getElementById["demo"].innerHTML = err.name; }Try it »
#4. Syntax Error

Một lỗi SyntaxError được ném [throw] ra nếu bạn cố gắng evaluate code với một cú pháp lỗi:

Ví dụ:try { eval["alert['Hello]"]; // Lỗi vì thiếu dấu nháy ' } catch[err] { document.getElementById["demo"].innerHTML = err.name; }Try it »
#5. Type Error

Một lỗi TypeError được ném [throw] ra nếu bạn sử dụng giá trị nằm ngoài phạm vi của type được mong đợi:

Ví dụ:var num = 1; try { num.toUpperCase[]; // Không thể chuyển đổi một số thành chữ hoa } catch[err] { document.getElementById["demo"].innerHTML = err.name; }Try it »
#6. URI [Uniform Resource Identifier] Error

Một lỗi URIError được ném [throw] ra nếu bạn sử dụng các ký tự không hợp lệ trong hàm URI:

Ví dụ:try { decodeURI["%%%"]; // Không thể URI giải mã [decode] các ký tự phần trăm } catch[err] { document.getElementById["demo"].innerHTML = err.name; }Try it »
Bắt lỗi trong catch block

Trường hợp các xử lý ở khối try có thể phát sinh lỗi mà bạn dự đoán được thì trong khối catch có thể sử dụng câu lệnh if xử lý riêng cho từng lỗi.

Ví dụ:try { // các lệnh thực thi có thể phát sinh lỗi // ... } catch [e] { if [e instanceof TypeError] { // các lệnh handle TypeError exception } else if [e instanceof RangeError] { // các lệnh handle RangeError exception } else if [e instanceof EvalError] { // các lệnh handle EvalError exception } else { // Xử lý ngoại lệ chung mà không dự đoán được logMyErrors[e]; // pass exception object to error handler } }
5. Khối lệnh try/catch/finally có thể được lồng [nested] vào nhau

5. Khối lệnh try/catch/finally có thể được lồng [nested] vào nhau

Đầu tiên, hãy xem điều gì xảy ra với ví dụ bên dưới:

Ví dụ :try { try { throw new Error['oops']; } finally { console.log['finally']; } } catch [ex] { console.error['outer', ex.message]; } // Output: // "finally" // "outer" "oops"Try it »

Bây giờ, chúng ta sẽ thêm một khối catch vào bên trong khối try-block inner:

Ví dụ :try { try { throw new Error['oops']; } catch [ex] { console.error['inner', ex.message]; } finally { console.log['finally']; } } catch [ex] { console.error['outer', ex.message]; } // Output: // "inner" "oops" // "finallyTry it »

Và bây giờ, sẽ ném lại lỗi throw [re-throw error] ở khối catch vừa thêm vào:

Ví dụ :try { try { throw new Error['oops']; } catch [ex] { console.error['inner', ex.message]; throw ex; } finally { console.log['finally']; } } catch [ex] { console.error['outer', ex.message]; } // Output: // "inner" "oops" // "finally" // "outer" "oops"Try it »

Như vậy, qua 3 ví dụ , , chúng ta thấy:

  • Ngoại lệ [exception] chỉ được bắt [catch] một lần bởi khối catch bao quanh gần nhất trừ khi nó được ném lại [re-throw].
  • Tất nhiên, bất kỳ ngoại lệ mới [new exception] nào được raised lên bên trong khối inner [vì code trong khối catch có thể throw ra một vài lỗi j đó] sẽ bị chặn bởi khối outer.

Trường hợp return từ finally block

Ở ví dụ , chúng ta sẽ thêm lệnh return; vào finally block thì kết quả sẽ thế nào?

Nếu finally block trả về một giá trị, thì giá trị này sẽ trở thành giá trị trả về của toàn bộ quá trình try-catch-finally, bất kể có bất kỳ câu lệnh return nào trong khối try và catch. Điều này bao gồm các exception được ném vào bên trong khối catch.

Ví dụ:[function[] { try { try { throw new Error['oops']; } catch [ex] { console.error['inner', ex.message]; throw ex; } finally { console.log['finally']; return; } } catch [ex] { console.error['outer', ex.message]; } }][]; // Kết quả output: // "inner" "oops" // "finally"Try it »
Cảm ơn bạn đã theo dõi. Đừng ngần ngại hãy cùng thảo luận với chúng tôi!
0 0 votes
Đánh giá bài viết

Video liên quan

Chủ Đề