Exception Handling
Обробка винятків.
JavaScript має клас Error
, який можна використовувати для винятків. Ви видаєте помилку з ключовим словом throw
. Ви можете зловити його за допомогою пари блоків try
/ catch
, наприклад.
try {
throw new Error('Something bad happened');
}
catch(e) {
console.log(e);
}
Error Sub Types
Подтипи помилок.
Окрім вбудованого класу Error
, є кілька додаткових вбудованих класів помилок, які успадковують від Error
, які може викликати середовище виконання JavaScript:
RangeError
Створює екземпляр, що представляє помилку, яка виникає, коли числова змінна або параметр виходить за межі допустимого діапазону.
// Виклик з перевіщенною кількістю аргументів
console.log.apply(console, new Array(1000000000)); // RangeError: Недійсна довжина масиву
ReferenceError
Створює екземпляр, що представляє помилку, яка виникає під час використання недійсного посилання. Наприкллад:
'use strict';
console.log(notValidVar); // ReferenceError: notValidVar не визначено
SyntaxError
Створює екземпляр, що представляє синтаксичну помилку, яка виникає під час аналізу коду, який не є дійсним JavaScript.
1***3; // SyntaxError: Несподіваний маркер *
TypeError
Створює екземпляр, що представляє помилку, яка виникає, коли змінна або параметр має недійсний тип.
('1.2').toPrecision(1); // TypeError: '1.2'.toPrecision не є функцією
URIError
Створює екземпляр, що представляє помилку, яка виникає, коли encodeURI()
або decodeURI()
передають недійсні параметри.
decodeURI('%'); // URIError: неправильний URI
Always use Error
Error
Початківці розробники JavaScript іноді просто кидають необроблені рядки, наприклад.
try {
throw 'Something bad happened';
}
catch(e) {
console.log(e);
}
Don't do that. Фундаментальна перевага об’єктів Error
полягає в тому, що вони автоматично відстежують, де вони були створені та що іх викликало за допомогою властивості stack
.
Необроблені рядки призводять до дуже болісного досвіду налагодження та ускладнюють аналіз помилок із журналів.
You don't have to throw
an error
throw
an errorПередавати об’єкт Error
можна. Це традиційно для коду стилю зворотного виклику Node.js, який приймає зворотні виклики з першим аргументом як об’єкт помилки.
function myFunction (callback: (e?: Error)) {
doSomethingAsync(function () {
if (somethingWrong) {
callback(new Error('This is my error'))
} else {
callback();
}
});
}
Exceptional cases
Exceptions should be exceptional
(Винятки мають бути винятковими) — загальний вислів у інформатиці. Є кілька причин, чому це також стосується JavaScript (і TypeScript).
Unclear where it is thrown
Розглянемо такий фрагмент коду:
try {
const foo = runTask1();
const bar = runTask2();
}
catch(e) {
console.log('Error:', e);
}
Наступний розробник не може знати, яка функція може викликати помилку. Людина, яка переглядає код, не може знати, не прочитавши код для task1 / task2 та інших функцій, які вони можуть викликати тощо.
Makes graceful handling hard
Ви можете спробувати зробити це витонченим, чітко зафіксувавши кожну річ, яка може викинути:
try {
const foo = runTask1();
}
catch(e) {
console.log('Error:', e);
}
try {
const bar = runTask2();
}
catch(e) {
console.log('Error:', e);
}
Але тепер, якщо вам потрібно передати матеріали з першого завдання до другого, код стає безладним: (зверніть увагу на мутацію foo
, що вимагає let
+ явну потребу анотувати це, оскільки це не можна вивести з повернення runTask1
) :
let foo: number; // Notice use of `let` and explicit type annotation
try {
foo = runTask1();
}
catch(e) {
console.log('Error:', e);
}
try {
const bar = runTask2(foo);
}
catch(e) {
console.log('Error:', e);
}
Not well represented in the type system
Розглянемо функцію:
function validate(value: number) {
if (value < 0 || value > 100) throw new Error('Invalid value');
}
Використання Error
для таких випадків є поганою ідеєю, оскільки воно не представлено у визначенні типу для функції перевірки (це (value:number) => void
). Натомість кращим способом створення методу перевірки буде:
function validate(value: number): {error?: string} {
if (value < 0 || value > 100) return {error:'Invalid value'};
}
А тепер його представлено в системі типів.
Якщо ви не хочете обробити помилку дуже загальним (простим/всеохоплюючим тощо), не генеруйте помилку.
Last updated