Câu lệnh quản lý lỗi
Bạn có thể ném ngoại lệ (Exception) bằng cách sử dụng câu lệnh throw
và xử lý ngoại lệ bằng cách sử dụng câu lệnh try ... catch
.
Chúng ta có thể ném bất cứ kiểu Exception nào.
Ví dụ
1
2
3
4
5
6
7
8
|
throw 'Error2'; // kiểu String
throw 42; // kiểu Number type
throw true; // kiểu Boolean
throw { // kiểu Object
toString() {
return "I'm an object!";
}
};
|
Thường thì chúng ta sẽ tạo một đối tượng riêng để ném ngoại lệ.
1
2
3
4
5
6
7
8
9
|
// Tạo một đối tượng kiểu UserException
function UserException(message) {
this.message = message;
this.name = 'UserException';
this.toString = function() {
return `${this.name}: "${this.message}"`;
}
}
throw new UserException('Value too high');
|
Câu lệnh try ... catch
Câu lệnh try ... catch
kiểm tra một khối các câu lệnh và nếu một ngoại lệ được ném ra, câu lệnh catch
sẽ bắt nó. Nếu ngoại lệ được ném ra trong khối try
các câu lệnh sau nó không được thực thi mà thực thi ngay khối catch
.
Ví dụ:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
function getMonthName(mo) {
mo = mo - 1; // Thay đổi index của array (1 = Jan, 12 = Dec)
let months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
if (months[mo]) {
return months[mo];
} else {
throw 'InvalidMonthNo'; // ném ra một ngoại lệ
}
}
try { // câu lệnh try
monthName = getMonthName(13); // Hàm này có thể ném ra lỗi
}
catch (e) {
// xử lý khi có lỗi
console.error(e);
}
|
Để in lỗi ra console
chúng ta nên sử dụng console.error()
thay vì console.log()
Khối lệnh finally
Khối finally
chứa các câu lệnh sẽ được thực thi sau khi các khối thử và bắt thực thi. Cần lưu ý khối finally
sẽ thực thi cho dù có ném ngoại lệ hay không.
Ví dụ sau đây mở một file và sau đó thực thi các câu lệnh sử dụng file. (Nodejs cho phép truy cập các file.) Sử dụng finally
ở đây đảm bảo file không bao giờ bị mở, ngay cả khi xảy ra lỗi.
1
2
3
4
5
6
7
8
|
openMyFile();
try {
writeMyFile(theData); // Câu lệnh này có thể ném ngoại lệ
} catch(e) {
handleError(e); // Nếu ngoại lệ xảy ra thì xử lý
} finally {
closeMyFile(); // Đóng lại các tài nguyên đã sử dụng
}
|
Nếu khối finally
return một giá trị, giá trị này sẽ trở thành giá trị trả về của toàn bộ khối try ... catch ... finally
, bất kể câu lệnh return nào khác trong khối try
và catch
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
function f() {
try {
console.log(0);
throw 'bogus'; // ném ra một ngoại lệ
} catch(e) {
console.log(1);
return true; // câu lệnh return này bị chặn lại
// nhường chỗ cho khối lệnh finally
console.log(2); // không chạy câu lệnh này
} finally {
console.log(3);
return false; // chạy đè câu lệnh `return` trước
console.log(4); // không chạy câu lệnh này
}
console.log(5); // không chạy câu lệnh này
}
console.log(f()); // 0, 1, 3, false
|
Ghi đè các giá trị trả về của khối finally
cũng áp dụng cho các ngoại lệ được ném hoặc ném lại bên trong khối catch
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
function f() {
try {
throw 'bogus';
} catch(e) {
console.log('Bắt bên trong "bogus"');
throw e; // Câu lệnh này bị chặn lại tới khi finally thực thi xong
} finally {
return false; // ghi đè câu lệnh throw ở trước
// có nghĩa hàm này chỉ retur false, không ném
// ngoại lệ
}
}
try {
console.log(f()); // thực thi hàm f(), trả về false
} catch(e) {
// Đoạn code này không chạy vì
// không có ngoại lệ nào được ném trong f()
console.log('Bắt bên ngoài "bogus"');
}
// ->
// Bắt bên trong "bogus"
// false
|