Обработка ошибок в JavaScript
1. Что такое Error?
Для начала рассмотрим пример, в данном примере я вызываю метод объекта, но данный объект на самом деле не имеет этот метод, и происходит ошибка.
hello-error-example.js
console.log("Three");
let myObj = {};
console.log("Two");
console.log("One");
// Объект myObj не имеет метода showMe().
// Но мы вызываем метод showMe().
// И ошибка происходит здесь.
myObj.showMe(); // ==> Error!!!!!!!!!
// Срока кода ниже не будет выполнена.
console.log("Let's go!");
Результат запуска примера:
Вы можете увидеть уведомление ошибки на экране Console, уведомление ошибки очень понятное, на какой строке кода это произошло.
Вы можете увидеть уведомление ошибки на экране Console, уведомление ошибки очень понятное, на какой строке кода это произошло.
Просмотрите поток программы через следующее изображение.
- Программа запущена абсолютно нормально в шагах (1), (2), (3), (4)
- Шаг (5) происходит ошибка, когда вы пытаетесь вызвать метод объекта, хотя этот объект не имеет данный метод.
- Код в шаге (6) не будет выполнен.
2. Обработка ошибок с помощью try-catch
Ошибки могут произойти во время работы (runtime) программы, может быть неожиданная вами ошибка. Используйте try-catch чтобы помочь найти и обработать ошибку при происхождении.
Вернитесь к примеру выше, мы добавим try-catch чтобы найти и обработать ошибку.
hello-catch-example.js
console.log("Three");
let myObj = {};
console.log("Two");
console.log("One");
try {
// Объект myObj не имеет метод showMe().
// Но мы вызываем метод showMe().
// И ошибка происходит здесь.
myObj.showMe(); // ==> Error!
// Данный код будет пропущен
console.log("!!!");
} catch (e) {
console.log("Catched error: " + e);
console.log("OK continue...");
}
console.log("Let's go!");
И результаты запуска примера:
Three
Two
One
Catched error: TypeError: myObj.showMe is not a function
OK continue...
Let's go!
Изображение ниже объясняет поток (flow) программы:
- Шаги (1)-(4) абсолютно нормальны.
- Исключение происходит в шаге (5), кода вы пытаетесь вызвать метод объекта, но объект не имеет данный метод.
- Он сразу же прыгает выполнять команду в блоке catch, шаг (6) пропускается.
- Шаг (7), (8) будет выполнен.
- Шаг (9 будет выполнен.
3. Блок try-catch-finally
Выше мы ознакомились с обработкой исключений через блок try-catch. Полная обработка ошибки использует try-catch-finally. Блок finally всегда выполняется, несмотря не то, происходит ошибка в блоке try или нет.
try {
// Сделать что-то здесь.
} catch (e ) {
// Сделать что-то здесь.
} finally {
// Блок finally всегда выполняется.
// Сделать что-то здесь.
}
Пример:
try-catch-finally-example.js
function getGreeting(language) {
try {
console.log("Code in try block (*)");
// Вызвать метод greeting() объекта 'language'.
// Здесь может выброситься исключение
// если даный объект не имеет метода greeting()
let v = language.greeting();
console.log("Code in try block (**)");
return v;
} catch (e) {
console.log("Code in catch block. Something Error: " + e);
} finally {
// Блок 'catch' будет выполнен.
console.log("Code in finally block");
}
return " !! ";
}
// ----------------------- TEST ---------------------------------
// Test 1:
console.log("----- Call getGreeting(null) -----");
let v1 = getGreeting(null);
console.log("Greeting: " + v1);
// Test 2:
console.log("------ Call getGreeting(language) ------");
let language = new Object();
language.greeting = function() {
return "Hello Everybody";
}
let v2 = getGreeting(language);
console.log("Greeting: " + v2);
Запуск примера:
----- Call getGreeting(null) -----
Code in try block (*)
Code in catch block. Something Error: TypeError: Cannot read property 'greeting' of null
Code in finally block
Greeting: !!
----- Call getGreeting(language) -----
Code in try block (*)
Code in try block (**)
Code in finally block
Greeting: Hello Everybody
Изображение ниже иллюстрирует поток программы при происхождении ошибки в блоке try, блок finally всегда выполняется.
Изображение ниже иллюстрирует поток программы если нет ошибки в блоке try. В данном случае блок finally выполняется сразу перед выполнением команды return блока try.
4. Built-in Errors
ECMAScript имеет встроенные классы для представления ошибки, ниже является их иерархия (heirachy).
RangeError
RangeError выбрасывается если вы используете число вне разрешаемого диапазона.
error-RangeError-example.js
let num = 1;
try {
// A number cannot have 500 significant digits
num.toPrecision(500); // ==> RangeError!!
}
catch(err) {
console.log(err.name);
console.log(err);
}
ReferenceError
ReferenceError выбрасывается (throw) если вы используете переменную, которая не была объявлена.
error-ReferenceError-example.js
var x;
try {
x = y + 1; // y cannot be referenced (used)
}
catch(err) {
console.log("Error Name: "+ err.name);
console.log(err);
}
SyntaxError
SyntaxError выбрасывается (throw) если вы пытаетесь оценить (evaluate) код содержащий ошибку синтаксиса.
error-SyntaxError-example.js
try {
let x;
eval(" x = 'Hello "); // Missing ' will produce an error
}
catch(err) {
console.log("Error Name: " + err.name);
console.log(err);
}
TypeError
TypeError выбрасывается (throw) если вы используете значение неожидаемого вида. Например ошибка происходит, когда вы вызываете метод объект, и объект не имеет данный метод.
error-TypeError-example.js
var num = 1;
try {
num.toUpperCase(); // Number has no method toUpperCase()
}
catch(err) {
console.log("Error Name: " + err.name);
console.log(err);
}
URIError
URIError выбрасывается (throw) если вы используете символы недопустимые в функции URI:
error-URIError-example.js
try {
decodeURI("%%%"); // You cannot URI decode percent signs
}
catch(err) {
console.log("Error Name: " + err.name);
console.log(err);
}
5. Выбросить Error
ECMAScript позволяет вам выбросить (throw) нечто во время работы программы, программа будет считать что произошла ошибка.
throw-any-example.js
console.log(" -------- Test throw any object ------------");
try {
let myObj = {};
throw myObj;
} catch(e) {
console.log("Catch error: ");
console.log(e);
}
console.log(" -------- Test throw a Symbol ------------");
try {
let mySymbol = Symbol();
throw mySymbol;
} catch(e) {
console.log("Catch error: ");
console.log(e);
}
console.log(" -------- Test throw a Number ------------");
try {
let myNumber = 100;
throw myNumber;
} catch(e) {
console.log("Catch error: ");
console.log(e);
}
console.log(" -------- Test throw a String ------------");
try {
let myString = "Some error";
throw myString;
} catch(e) {
console.log("Catched error: ");
console.log(e);
}
Output:
-------- Test throw any object ------------
Catch errorr:
{}
-------- Test throw a Symbol ------------
Catch error:
Symbol()
-------- Test throw a Number ------------
Catch error:
100
-------- Test throw a String ------------
Catched error:
Some error
Обычно вы используете класс Error чтобы создать объект ошибки. Другие классы как SyntaxError, InternalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError так же можно использовать в подходящем контексте.
Объект ошибки создается через класс Error (или его подклассы), при выбрасывании (throw) он будет содержать важную информацию как файл из-за которого произошла ошибка, местоположение ошибки, и информацию помогающую вам найти ошибку.
throw-error-example.js
console.log("Three");
// Create an Error
let myError = new Error("Something error!");
console.log("Two");
// Throw it!
throw myError;
console.log("One");
В простом случае вы можете выбросить что угодно, не объект класса Error (Или его подклассы). Но при нахождении ошибок данного вида вы не сможете имет информация как файл из-за которого происходит ошибка, местоположение происхождения ошибки,...
throw-string-error-example.js
console.log("Three");
try {
console.log("Two");
// Throw a String!
throw "Some error!!";
} catch(e) {
console.log("typeof e = " + (typeof e));
// Log the error
console.log(e); // Some error!!
}
console.log("One");
Output:
Three
Two
typeof e = string
Some error!!
One
В ECMAScript, каждый блок try имеет соответствующий блок cache. Но в блоке try могут произойти разные виды ошибок, в данном случае вам нужно проверить ошибку найденную в блоке catch чтобы предоставить подходящую обработку для каждого вида ошибки.
catch-complex-example.js
let err = new Error("My Error");
let rangeErr = new RangeError();
let evalErr = new EvalError("My Eval Error");
// A random value in [0.. 9]
let randomValue = Math.floor(Math.random() * 10);
// [0,1,2,3]
let random0123 = randomValue % 4;
console.log("random0123 = " + random0123);
try {
if(random0123 == 0) {
throw err;
} else if(random0123 == 1){
throw rangeErr;
} else if(random0123 == 2) {
throw evalErr;
} else if(random0123 == 3) {
throw "A String Error";
}
} catch(e) {
console.log("typeof e = " + (typeof e));// 'object' or 'string'
if(e instanceof RangeError) {
console.log("--> RangeError!!");
} else if(e instanceof EvalError) {
console.log("--> EvalError!!");
} else if(e instanceof Error) {
console.log("--> Error!!");
} else if (typeof e == "string"){
console.log("--> String Error!!");
} else {
console.log("--> Error!!");
}
console.log(e);
}
6. Свойства Error
В ECMAScript, ошибка которую вы нашли может быть "Error object" или любой вид данных. Если это "Error object" у вас будет важная информация как название файла создавшая ошибку, местоположение ошибки, Stack Trace,..
Есть некоторые важные свойства (property) класса Error:
- name: Название ошибки.
- message: Содержание ошибки.
- stack (Readonly): текст содержащий информацию, помогающая вам найти местоположение ошибки.
error-properties-example.js
// Create an Error
let myError = new Error();
myError.name = "MyError";
myError.message = "My Error String";
try {
throw myError;
} catch(err) {
console.log("Error Name: " + err.name);
console.log("Error Message: " + err.message);
console.log("Type of err.stack: " + (typeof err.stack));
console.log("--- Stack Trace: ---");
console.log(err.stack);
}
7. Перевыбросить ошибку (Re-throw Error)
При обработке исключения вы можете схватить это исключение и обработать или перевыбросить (rethrow) его наружу.
rethrow-example.js
function checkScore(score) {
if (score < 0 || score > 100) {
throw "Invalid Score " + score;
}
}
function checkPlayer(name, score) {
try {
checkScore(score)
} catch (e) {
// Сделать что-то с exception
console.log("Something invalid with player: " + name + " >> " + e);
// Перевыбросить наружу.
throw e;
}
console.log("OK Player " + name + " has score: " + score );
}
// --------------- TEST --------------
checkPlayer("Tom", 90);
checkPlayer("Jerry", -10);
Например, схватить исключение и перевыбросить (rethrow) другое исключение.
rethrow-example2.js
function checkScore(score) {
if (score < 0 || score > 100) {
throw "Invalid Score " + score;
}
}
function checkPlayer(name, score) {
try {
checkScore(score)
} catch (e) {
// Сделать что-то с exception
console.log("Something invalid with player: " + name + " >> " + e);
// Потом выбросить другое исключение
throw ("Score " + score +" invalid for player " + name);
}
console.log("OK Player " + name + " has score: " + score );
}
// --------------- TEST --------------
checkPlayer("Tom", 90);
checkPlayer("Jerry", -10);
8. Исключения при схватке ошибок
В ECMAScript имеются ситуации, когда вы думаете возникнет ошибка, но это не происходит. Например деление на 0 не создает ошибку, результат возвращает Infinity или -Infinity.
ex-Infinity-example.js
console.log( typeof Infinity ); // number
let a = 1 / 0;
console.log(a); // Infinity
let b = -1 / 0;
console.log(b); // -Infinity
Возьмите значение не число, чтобы поделить на число, результатом будет NaN (Not a Number).
ex-NaN-example.js
console.log( typeof NaN ); // number
console.log( isNaN(1) ); // false
console.log( isNaN( NaN ) ); // true
let a = "A String" / 2;
console.log(a); // NaN
let obj = {};
let b = obj / 2;
console.log(b); // NaN
Вы можете получить доступ в элемент с индексом любого массива (Array) не вызывая ошибку.
ex-array-index-example.js
let myArray = [1, 100, 20];
console.log( myArray[1]); // 100
console.log( myArray[10] ); // undefined
console.log( myArray[-10] ); // undefined
Pуководства ECMAScript, Javascript
- Введение в Javascript и ECMAScript
- Быстрый старт с Javascript
- Диалоговое окно Alert, Confirm, Prompt в Javascript
- Быстрый запуск с JavaScript
- Переменные (Variable) в JavaScript
- Битовые операции
- Массивы (Array) в JavaScript
- Циклы в JavaScript
- Руководство JavaScript Function
- Руководство JavaScript Number
- Руководство JavaScript Boolean
- Руководство JavaScript String
- Заявление if/else в JavaScript
- Заявление Switch в JavaScript
- Обработка ошибок в JavaScript
- Руководство JavaScript Date
- Руководство JavaScript Module
- Функция setTimeout и setInterval в JavaScript
- Руководство Javascript Form Validation
- Руководство JavaScript Web Cookie
- Ключевое слово void в JavaScript
- Классы и объекты в JavaScript
- Техника симулирования класса и наследственности в JavaScript
- Наследование и полиморфизм в JavaScript
- Понимание Duck Typing в JavaScript
- Руководство JavaScript Symbol
- Руководство JavaScript Set Collection
- Руководство JavaScript Map Collection
- Понимание JavaScript Iterable и Iterator
- Руководство Регулярное выражение JavaScript
- Руководство JavaScript Promise, Async Await
- Руководство Javascript Window
- Руководство Javascript Console
- Руководство Javascript Screen
- Руководство Javascript Navigator
- Руководство Javascript Geolocation API
- Руководство Javascript Location
- Руководство Javascript History API
- Руководство Javascript Statusbar
- Руководство Javascript Locationbar
- Руководство Javascript Scrollbars
- Руководство Javascript Menubar
- Руководство JavaScript JSON
- Обработка событий в Javascript
- Руководство Javascript MouseEvent
- Руководство Javascript WheelEvent
- Руководство Javascript KeyboardEvent
- Руководство Javascript FocusEvent
- Руководство Javascript InputEvent
- Руководство Javascript ChangeEvent
- Руководство Javascript DragEvent
- Руководство Javascript HashChangeEvent
- Руководство Javascript URL Encoding
- Руководство Javascript FileReader
- Руководство Javascript XMLHttpRequest
- Руководство Javascript Fetch API
- Разбор XML в Javascript с помощью DOMParser
- Введение в Javascript HTML5 Canvas API
- Выделение кода с помощью библиотеки Javascript SyntaxHighlighter
Show More