Наистина ли имаме нужда от него?
Когато започнахме да проектираме нашия корпоративен клиент, помолихме нашия UX дизайнер да ни даде някои съвети относно дизайна как да се справяме с грешките от задния сървър в приложението. Трябва ли да е изскачащ прозорец, тостер или съобщение за грешка близо до входа?
Отговорът му не беше това, което очаквахме, „трябва да няма никаква грешка във вашето приложение !'
Обяснихме, че в нашето приложение потребителят може да извършва много невалидни действия, които не са разрешени и трябва да покажем грешка от бекенд сървъра. В края на краищата, това е корпоративно приложение...
Отговорът му беше доста честен, предотвратете на потребителя действията, които не са разрешени за извършване.
И така, за какво още трябва да се тревожим? Неочаквани грешки, тъй като за очаквани грешки можем да направим план и добър поток на потребителския интерфейс.
Неочакваните грешки са много технически и обикновеният потребител не може да направи нищо с тази информация (заключване на DB, грешка в синтаксиса на заявката, изключение за нулев указател, прекъсната връзка...). Така че е достатъчно да кажете на потребителя, че „нещо се обърка“.
За тези случаи е добро UX поведение да показвате изскачащ прозорец или каквото и да е грозно решение, което искате.
Проектирайте нашия манипулатор на грешки
Искаме да направим услуга, която улавя всяка неочаквана грешка в приложението, като например следното:
- Ако това е грешка от нашия бек-енд сървър, тогава искаме да покажем тостер с някакво съобщение, че нещо се е объркало и потребителят може да опита отново по-късно... когато потребителят щракне, за да го отхвърли, страницата ще бъде опреснена (ние ще предложи по-добро решение по-късно).
- Ако това е неупълномощена грешка (сесията е изтекла), навигирайте потребителя до страницата за вход.
- Ако е забранено, навигирайте потребителя до страница, която описва, че той/тя се нуждае от повече разрешения, за да извърши това действие.
Във всеки случай ние ще регистрираме грешката в конзолата, този разработчик може да я отстрани.
Нека го направим стъпка по стъпка:
- Прилагане
ErrorHandler
Angular има интерфейс ErrorHandler
in@angular/core.
Нека създадем нов клас, който ще го имплементира.
2. Приложете handleError(error: any): void
Някои бележки:
- Използвах две външни библиотеки: ng2-toastr и http-status-codes (ако сте използвали typescript, ще трябва да добавите @types/http-status-codes)
- Всички наши грешки в задния край имат поле
httpErrorCode.
Ние разчитаме на него, за да правим разлика между различните типове грешки. Ако няма такова поле, вероятно е грешка, причинена от кода на клиента.
3. Предоставете нашата услуга в основния модул: (моля, руутнете, за да го направите сингълтон)
provide: ErrorHandler,useClass: MyAppErrorHandler
И сме готови!!!
Нека направим крачка напред:
Опресняването на страницата не е най-доброто решение. И така, какво е по-добре? Зависи от нашия случай на употреба. Нека дадем на нашите UI компоненти/услуги силата да изпращат обратно извикване в обекта за грешка. Нашата услуга за обработка на грешки ще го извика и когато потребителят отхвърли грешката, тя се появява в тоста.
В кода по-долу имам услуга за премахване на елемент, извикване на API от задния край, за да го премахна също. И в случай на грешка, добавям към обекта за грешка обратно извикване, което знае да добави отново изтрития елемент.
Сценарият ще бъде: потребителят изтрива елемент, получава съобщение: „нещо се обърка, опитайте отново по-късно“, потребителят кликва върху съобщението, за да отхвърли елемент, който се добавя отново към списъка, както беше преди изключението.
Нашият манипулатор ще бъде малко променен: вместо да извикваме наивното опресняване:window.location.reload
, ще направим error.callback?error.callback():window.location.reload;
Достатъчно ли е?
Предпочитам да извадя работата по структурирането на грешки от нашата компонентна логика и да я преместя в зоната за HTTP заявка. Компонентът просто ще знае да подготви обратното извикване и да го изпрати до услугата, която прави HTTP. Това ще структурира обратното извикване вътре в обекта за грешка и ще хвърли отново.
Сега нашият deletItem
API ще бъде по-прост:
И задната HTTP заявка ще бъде:
В случай, че вашите HTTP заявки имат някаква обща програма, можете да преместите тази логика там и да я напишете веднъж. В моя случай HTTP заявките се генерират от някакъв шаблон, който подготвих, така че просто трябва да актуализирам шаблона с тази промяна на преструктурирането на грешката.