Помилки
Поговоримо про помилки.
Існує два типи помилок:
- очікувані помилки
- несподівані помилки
- помилки один за одним
Очікувані помилки
Очікувані помилки - це стани, коли трапляється неправильна річ, але ви знаєте, що це може статися, тому ви вирішуєте це.
Це такі речі, як введення користувача або запити сервера. Ви знаєте, що користувач може помилитися або що сервер може бути відключений, тому ви пишете якийсь перевіряючий код, щоб переконатися, що програма знову запитує введення, або відображає повідомлення чи будь-яку іншу поведінку.
Вони підлягають відшкодуванню при обробці. Якщо залишити своє повідомлення, вони стають несподіваними помилками.
Несподівані помилки
Несподівані помилки (помилки) - це стани, коли трапляється неправильна річ, оскільки код неправильний. Ви знаєте, що вони врешті-решт відбудуться, але немає способу дізнатися, де чи як боротися з ними, оскільки, за визначенням, вони несподівані.
Це такі речі, як синтаксичні та логічні помилки. У вас може бути помилка друку у коді, можливо, ви викликали функцію з неправильними параметрами. Зазвичай вони не підлягають відшкодуванню.
try..catch
Поговоримо try..catch
.
У JavaScript throw
не використовується часто. Якщо ви подивитесь на приклади в коді, їх буде мало і далеко між собою, і зазвичай структуровано за рядками
function example(param) {
if (!Array.isArray(param) {
throw new TypeError('"param" should be an array!');
}
...
}
Через це, try..catch
блоки теж не так часто зустрічаються для потоку управління. Зазвичай досить легко додати кілька перевірок перед викликом методів, щоб уникнути очікуваних помилок.
Навколишнє середовище JavaScript також прощає, тому несподівані помилки часто також залишаються без уваги.
try..catch
не повинно бути рідкістю. Є кілька приємних випадків використання, які є більш поширеними в таких мовах, як Java та C #. Java та C # мають перевагу введених catch
конструкцій, так що ви можете розмежувати очікувані та несподівані помилки:
C # :
try
{
var example = DoSomething();
}
catch (ExpectedException e)
{
DoSomethingElse(e);
}
Цей приклад дозволяє іншим несподіваним виняткам з'являтися та оброблятись в іншому місці (наприклад, шляхом реєстрації та закриття програми).
У JavaScript цю конструкцію можна реплікувати за допомогою:
try {
let example = doSomething();
} catch (e) {
if (e instanceOf ExpectedError) {
DoSomethingElse(e);
} else {
throw e;
}
}
Не такий елегантний, що є частиною причини, чому це нечасто.
Функції
Поговоримо про функції.
Якщо ви використовуєте принцип єдиної відповідальності , кожен клас та функція повинні слугувати єдиному призначенню.
Наприклад, authenticate()
може автентифікувати користувача.
Це може бути записано як:
const user = authenticate();
if (user == null) {
// keep doing stuff
} else {
// handle expected error
}
Крім того, він може бути записаний так:
try {
const user = authenticate();
// keep doing stuff
} catch (e) {
if (e instanceOf AuthenticationError) {
// handle expected error
} else {
throw e;
}
}
Обидва прийнятні.
Обіцянки
Поговоримо про обіцянки.
Обіцяння - це асинхронна форма try..catch
. Зателефонувавши new Promise
або Promise.resolve
запустивши свій try
код. Зателефонував throw
або Promise.reject
надішле вам catch
код.
Promise.resolve(value) // try
.then(doSomething) // try
.then(doSomethingElse) // try
.catch(handleError) // catch
Якщо у вас є асинхронна функція для автентифікації користувача, ви можете написати це як:
authenticate()
.then((user) => {
if (user == null) {
// keep doing stuff
} else {
// handle expected error
}
});
Крім того, він може бути записаний так:
authenticate()
.then((user) => {
// keep doing stuff
})
.catch((e) => {
if (e instanceOf AuthenticationError) {
// handle expected error
} else {
throw e;
}
});
Обидва прийнятні.
Гніздування
Поговоримо про гніздування.
try..catch
можна вкласти. Ваш authenticate()
метод може мати внутрішній try..catch
блок, такий як:
try {
const credentials = requestCredentialsFromUser();
const user = getUserFromServer(credentials);
} catch (e) {
if (e instanceOf CredentialsError) {
// handle failure to request credentials
} else if (e instanceOf ServerError) {
// handle failure to get data from server
} else {
throw e; // no idea what happened
}
}
Так само обіцянки можуть вкладатись. Ваш authenticate()
метод асинхронізації може внутрішньо використовувати обіцянки:
requestCredentialsFromUser()
.then(getUserFromServer)
.catch((e) => {
if (e instanceOf CredentialsError) {
// handle failure to request credentials
} else if (e instanceOf ServerError) {
// handle failure to get data from server
} else {
throw e; // no idea what happened
}
});
То яка відповідь?
Гаразд, я думаю, що саме час мені реально відповісти на питання:
Чи невдача в аутентифікації вважається чимось, від чого ви відкинете обіцянку?
Найпростіша відповідь, яку я можу дати, - це те, що ви повинні відхилити обіцянку в будь-якому місці, в іншому випадку ви хочете throw
зробити виняток, якби це був синхронний код.
Якщо ваш контрольний потік простіший, маючи кілька if
перевірок у своїх then
виписках, обіцянки відкидати не потрібно.
Якщо ваш потік управління простішим, відхиливши обіцянку і перевіривши на тип помилок у вашому коді обробки помилок, то зробіть це замість цього.
reject
і не повертати помилкове, але якщо ви очікуєте, що значення буде aBool
, то ви мали успіх і вам слід вирішити з Bool незалежно від значення. Обіцяння - це свого роду проксі-сервери для значень - вони зберігають повернене значення, тож лише якщо ви не зможете отримати це значенняreject
. Інакше слідresolve
.