Наистина ли имаме нужда от него?

Когато започнахме да проектираме нашия корпоративен клиент, помолихме нашия UX дизайнер да ни даде някои съвети относно дизайна как да се справяме с грешките от задния сървър в приложението. Трябва ли да е изскачащ прозорец, тостер или съобщение за грешка близо до входа?
Отговорът му не беше това, което очаквахме, „трябва да няма никаква грешка във вашето приложение !'
Обяснихме, че в нашето приложение потребителят може да извършва много невалидни действия, които не са разрешени и трябва да покажем грешка от бекенд сървъра. В края на краищата, това е корпоративно приложение...
Отговорът му беше доста честен, предотвратете на потребителя действията, които не са разрешени за извършване.
И така, за какво още трябва да се тревожим? Неочаквани грешки, тъй като за очаквани грешки можем да направим план и добър поток на потребителския интерфейс.
Неочакваните грешки са много технически и обикновеният потребител не може да направи нищо с тази информация (заключване на DB, грешка в синтаксиса на заявката, изключение за нулев указател, прекъсната връзка...). Така че е достатъчно да кажете на потребителя, че „нещо се обърка“.
За тези случаи е добро UX поведение да показвате изскачащ прозорец или каквото и да е грозно решение, което искате.

Проектирайте нашия манипулатор на грешки

Искаме да направим услуга, която улавя всяка неочаквана грешка в приложението, като например следното:

  • Ако това е грешка от нашия бек-енд сървър, тогава искаме да покажем тостер с някакво съобщение, че нещо се е объркало и потребителят може да опита отново по-късно... когато потребителят щракне, за да го отхвърли, страницата ще бъде опреснена (ние ще предложи по-добро решение по-късно).
  • Ако това е неупълномощена грешка (сесията е изтекла), навигирайте потребителя до страницата за вход.
  • Ако е забранено, навигирайте потребителя до страница, която описва, че той/тя се нуждае от повече разрешения, за да извърши това действие.

Във всеки случай ние ще регистрираме грешката в конзолата, този разработчик може да я отстрани.

Нека го направим стъпка по стъпка:

  1. Прилагане ErrorHandler

Angular има интерфейс ErrorHandler in@angular/core. Нека създадем нов клас, който ще го имплементира.

2. Приложете handleError(error: any): void

Някои бележки:

  1. Използвах две външни библиотеки: ng2-toastr и http-status-codes (ако сте използвали typescript, ще трябва да добавите @types/http-status-codes)
  2. Всички наши грешки в задния край имат поле 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 заявките се генерират от някакъв шаблон, който подготвих, така че просто трябва да актуализирам шаблона с тази промяна на преструктурирането на грешката.