Najważniejsze zagadnienia, które musisz znać
5 godz. 53 min · JavaScript · Full-stack i Programowanie
Adam GospodarczykPrzesyłanie oraz transformacja danych to jeden z najważniejszych elementów działania każdej aplikacji. Dobre zrozumienie tego w jaki sposób odbywa się ten proces, daje równocześnie lepsze zrozumienie całej struktury oraz podejmowania decyzji projektowych. W tym kursie znajdziesz lekcje, które pozwolą Ci uporządkować wiedzę na temat protokołu HTTP oraz formatów wymiany danych.
REST oraz GraphQL to nadal nieodłączone zagadnienia tematu wymiany informacji w kontekście aplikacji webowych. Pomimo tego, że ich koncepcje zwykle są bardzo dobrze opisane w różnych źródłach, tak ich wykorzystanie "na produkcji" potrafi sprawić problemy. W szczególności gdy weźmiemy pod uwagę, wyjątki oraz fakt, że nie każda aplikacja będzie wymagać implementacji REST czy GraphQL w 100%. W tym kursie znajdziesz wiele praktycznych wskazówek związanych z pracą z REST API oraz wprowadzenie do pracy z GraphQL.
Niektóre błędy w aplikacji są bardzo pożądane, w szczególności gdy jasno informują użytkownika o tym, co się wydarzyło oraz o tym, co może z tym zrobić. Pomimo tego, że w wielu przypadkach opracowanie komunikatów leży w rękach osoby odpowiedzialnej za copywriting (i/lub ux writing), tak sama implementacja tych komunikatów odbywa się po stronie kodu. Nie rzadko okazuje się, że poprawna i skuteczna walidacja danych oraz obsługa błędów nie jest oczywista w "produkcyjnych" sytuacjach. W tym kursie znajdziesz najczęściej spotykane problemy oraz sposoby ich rozwiązania.
Bazy danych są praktycznie nieodłączną częścią każdej aplikacji. W roli full-stacka prędzej czy później przyjdzie Ci z nimi pracować a nie rzadko nawet projektować oraz rozbudowywać ich struktury. W tym kursie znajdziesz informacje o bazach danych, które pozwolą Ci je zrozumieć oraz od razu poznać użyteczne techniki, które pomogą Ci w pracy z nimi, zarówno na produkcji jak i w środowisku lokalnym czy testowym.
Nie wszystkie informacje w aplikacji są publiczne. Niektóre wprost nie mogą takie być. Z tego powodu niezbędne są sposoby na to aby poznać a potem weryfikować tożsamość użytkownika, by na jej podstawie przydzielać mu dostęp wyłącznie do zasobów, do których odczytywania posiada uprawnienia. Istnieje wiele technik, które umożliwiają zarządzanie dostępem do danych i w tym kursie poznasz najważniejsze z nich. Dowiesz się nie tylko w jaki sposób zabezpieczać dane ale poznasz też najpopularniejsze sposoby na to aby te zabezpieczenia łamać i obchodzić. Mając świadomość takiej możliwości, będziesz w stanie lepiej podejmować decyzje o tym jak projektować dostęp do informacji.
Istnieją problemy charakterystyczne dla niemal każdej aplikacji. W związku z ich powszechnością, istnieje też szereg rozwiązań lub sposobów na to, aby możliwie zredukować ich następstwa. Na przestrzeni lekcji tego kursu zobaczysz wiele przykładów, które pomogą Ci w codziennej pracy a niekiedy nawet, pozwolą uniknąć błędów, których konsekwencje nie zawsze występują natychmiast.
Kurs powstał z myślą o osobach, które chcą rozwijać się w roli full-stack web developera / developerki, przeprowadzając przez najważniejsze zagadnienia z obszaru wymiany, transformacji oraz przechowywania informacji w aplikacji oraz pomiędzy aplikacjami. Jeżeli potrzebujesz zobaczyć szeroką perspektywę tego, w jaki sposób dane przepływają pomiędzy różnymi częściami aplikacji, lub ugruntować swoją wiedzę na ten temat, to ten kurs jest miejscem, którego szukasz.
W tej kwestii przejdziemy sobie przez
kwestie komunikacji w aplikacji webowej bardziej z perspektywy frontendu.
Domyślam się, że część z tych informacji może być dla Ciebie już doskonale znana,
ale zostań proszę ze mną, ponieważ uwzględnię tutaj kilka wątków.
Zacznijmy od tego, że zarówno w przypadku
frontendu, jak i backendu aktualnie wykorzystujemy Fetch API.
I tutaj jeżeli chodzi o środowisko node,
że jest to konieczne jest wykorzystanie paczki, które zasadniczo działa dokładnie
tak samo i jest po prostu odwzorowaniem tego API po stronie.
Wcześniej przez lata wykorzystywałem bibliotekę ACS, natomiast w tym momencie
raczej już nie ma większych powodów, aby po nią sięgać.
Może poza jakimiś kwestiami dotyczącymi kompatybilności.
W każdym razie, niezależnie z jakiego
narzędzia skorzystasz, konieczne będzie zrozumienie kilku wątków.
Przede wszystkim jeżeli chodzi o pracę z API.
Po pierwsze mamy metody HTTP, których rolą jest doprecyzowanie rodzaju akcji, którą
podejmujemy i jednocześnie nie jest to sposób na to, aby móc zmieniać zachowanie
dokładnie tej samej ścieżki, o czym za chwilę powiem.
Następnie, jeżeli chodzi o tworzenie zapytania mamy protokół HTTPS bądź http.
Natomiast w tym momencie praktycznie nie
ma już sytuacji, w której nie wykorzystujemy protokołu HTTPS.
Tym bardziej, że pokazywałem Ci nawet w
jaki sposób możesz skonfigurować go na komputerze lokalnym.
I naprawdę warto to zrobić, aby uniknąć
wszelkich niekompatybilności z kodem produkcyjnym zaraz po nim.
W niektórych przypadkach mamy do czynienia z opcjonalną domeną.
Czyli konkretniej jeżeli zapiszemy sobie
już pełny adres, to subdomena stanowi ten pierwszy fragment.
I teraz pokażę Ci na praktycznym przykładzie jak to dokładnie wygląda.
Mianowicie chociażby w przypadku Izy
mamy tutaj do czynienia ze stroną, która została stworzona z pomocą Web Flow i
jednocześnie sam i składa się z wielu różnych modułów.
I jednym z nich jest główna część aplikacji, czyli powiedzmy koszyk.
W tym momencie, pomimo tego, że nadal znajduje się w domenie Izy kpl.
To została tutaj dołączona subdomena app.
Podobnie jest w przypadku naszego projektu, w przypadku którego ponownie
strona główna została stworzona z pomocą Web Flow.
Ale już jeżeli dopiszemy sobie subdomenę commit, zostaniemy w ogóle przeniesieni do
zewnętrznej aplikacji, którą w tym przypadku jest platforma.
Zatem z punktu widzenia full stack, a na temat subdomen musisz wiedzieć tyle, że
umożliwiają one podłączenie różnych aplikacji w ramach jednej domeny.
Po prostu zamiast wymyślać zupełnie inną
domenę do obsługiwania, tak jak w tym przypadku części społeczności,
wykorzystaliśmy subdomenę, która dokładnie tym się zajęła.
I tutaj tylko dodam, że w zależności od tego jaki certyfikat SSL posiadasz,
konieczne będzie skonfigurowanie go również na potrzeby subdomen.
Sam w większości przypadków wykorzystuję certyfikaty Level crypt, które jest
bezpłatnym certyfikatem i też łatwo go skonfigurować.
Jeżeli chodzi o ten wątek, będziemy go
jeszcze poruszać przy okazji publikacji naszej aplikacji.
Wróćmy jednak do wątku komunikacji.
W momencie, gdy już mamy nasz podstawowy
adres URL, to jego kolejnym elementem jest konkretna ścieżka wewnątrz naszej domeny.
W kontekście API coś takiego nazywamy endpoint.
I tutaj najbardziej istotnym wątkiem jest
to, aby zachowywać spójną strukturę budowania takich adresów.
Chodzi o to, że tutaj ponownie pracując na froncie tylko korzystamy z gotowego API,
tak tutaj w roli full stack przyjdzie nam również je projektować.
Z tego powodu musimy poznać pewne reguły
dotyczące chociażby rest API, czyli takiego ogólnego, powszechnie używanego
zestawu reguł, które można wykorzystywać w projektowaniu własnych endpoint.
Tutaj ponownie, jeżeli chodzi o detale, będziemy sobie o nich jeszcze mówić.
Natomiast istotne jest tutaj to, że nawet
bez zaglądania do kodu jestem w stanie bardzo precyzyjnie określić, że zapytanie
wysłane na ten konkretny adres zwróci nam listę użytkowników.
Dodatkowo, dzięki temu, że mamy tutaj do
czynienia z rest API, jestem w stanie przewidzieć, że jeżeli zmienimy tutaj
zapytanie GET na post, to będę w stanie przesłać informację na temat nowego
użytkownika i też dopisać go do naszej bazy danych.
Inaczej mówiąc utworzyć nowy zasób.
I teraz kolejnym wątkiem, który należy tutaj poruszyć są parametry query String.
Służą one do doprecyzowania naszego zapytania i np.
określenia tego jak ma wyglądać odpowiedź, która zostanie przygotowana przez serwer.
W tym przypadku w związku z tym, że
wyświetlamy tutaj listę użytkowników i dodatkowo podajemy parametr limit.
To jest sygnał, które oczywiście musi zostać obsłużone po stronie backendu.
Do tego, aby zwrócić nam tagi listę użytkowników ograniczoną do 30 wyników.
Razem z odpowiedzią powinniśmy też otrzymać instrukcję od serwera, w jaki
sposób możemy pobrać kolejną porcję informacji.
Warto tutaj dodać, że w przypadku zapytań np.
zrealizowanych za pomocą metody POST
możliwe jest przesyłanie dodatkowych parametrów za pomocą tzw.
ciała zapytania, czyli request body.
W takiej sytuacji mamy większe możliwości jeżeli chodzi o to, co możemy tam zapisać.
W przypadku parametrów query Swing jesteśmy w stanie np.
zapisać je w historii przeglądarki, bądź po prostu skopiować i przekazać innemu
użytkownikowi, mając jednocześnie pewność, że trafi we właściwe miejsce.
Wyobraź sobie chociażby sytuację, w której
przeglądasz listę produktów na Amazonie i tam uwzględnione są parametry query string
określające, na której stronie aktualnie się znajdujesz.
W związku z tym, że wszystkie informacje na temat Twojej bieżącej lokalizacji są
zapisane jako Query String, jesteś w stanie skopiować ten adres i przekazać
komuś innemu, mając jednocześnie praktycznie pewność, że zobaczy to samo.
I teraz w niektórych sytuacjach może
okazać się tak, że dostęp do zasobu jest chroniony i dostępny wyłącznie dla
zalogowanych użytkowników i w dodatku takich, którzy posiadają odpowiednie
uprawnienia, aby upewnić się, że taki zasób jest odpowiednio chroniony.
Wykorzystujemy mechanizmy autoryzacji oraz uwierzytelnienia.
Jeżeli chodzi o autoryzację, mówimy o
procesie logowania, a uwierzytelnienie polega na tym, aby zweryfikować, czy
aktualny użytkownik, który wykonuje zapytanie ma dostęp do określonego zasobu.
No i teraz zwykle coś takiego realizowane jest z pomocą nagłówka Auto Organization,
które możemy dołączyć do dowolnego zapytania.
Jeżeli chodzi o sposób uwierzytelnienia.
Ponownie mamy tutaj do czynienia z różnego rodzaju standardami, ale jednocześnie mogą
one się różnić w zależności od API, z którym pracujemy bądź które projektujemy.
Z tego powodu musimy podjąć szereg projektowych decyzji dotyczących tego, w
jaki sposób będziemy weryfikować zapytania.
Temu również będziemy się przyglądać, w
szczególności jak możemy to zrobić z pomocą tzw.
Jackson Web Token.
Na ten temat z punktu widzenia full stack musisz przede wszystkim pamiętać o tym,
aby faktycznie zabezpieczyć ścieżki, do których nie powinni mieć dostępu
użytkownicy nieposiadający odpowiednich uprawnień.
Może to brzmieć absurdalnie, ale jest to
jeden z najczęstszych problemów związanych z bezpieczeństwem aplikacji.
Jednocześnie jest to na tyle obszerny wątek, że wrócimy do niego później.
Tymczasem poza nagłówkami dotyczącymi
autoryzacji bardzo często konieczne jest jeszcze określenie o rodzaju przesyłanych
danych oraz rodzaju danych, które spodziewamy się otrzymać od serwera.
W przypadku API niemal w każdym przypadku
jest to Jameson, aczkolwiek czasem zdarza się nam otrzymywać pliki tekstowe np.
HTML, bądź też po prostu pliki takie jak obrazki.
Wtedy również musimy je odpowiednio obsłużyć.
A tymczasem zobaczmy jeszcze jeden przykład, który w tym razem będzie
wykorzystywać metodę POST do tego, aby zapisać informacje o nowym użytkowniku.
Tak jak powiedziałem wcześniej, uderzamy dokładnie na ten sam endpoint, z tą
różnicą, że zamiast zapytania GET wykonujemy zapytanie typu POST.
Jest to bezpośrednia informacja dla naszej
aplikacji, że w tym momencie chcemy utworzyć nowy zasób.
Aby jego utworzenie było możliwe.
Teoretycznie moglibyśmy przekazać wymagane
informacje za pomocą query String, natomiast w przypadku zapytania typu post.
Zdecydowanie lepszym pomysłem i niemal w
każdej sytuacji wykorzystujemy wspominany request body.
W większości przypadków jest to nic innego jak obiekt, za pomocą którego przekazujemy
wszystkie niezbędne informacje do tego, aby utworzyć nowy zasób.
Jednocześnie zwrócić tutaj uwagę na pewien mały fakt.
Jeżeli chodzi o imię, nie ma tutaj zaskoczenia.
Przekazujemy po prostu ciąg znaków,
natomiast w przypadku projektu przekazujemy tutaj cyfrę 2.
Jeżeli zastanawiasz się z czego to konkretnie wynika, to jest to związane ze
sposobem przechowywania informacji po stronie serwera oraz bazy danych.
Oczywiście tutaj ponownie mówimy o
sytuacji, w której może się to różnić w zależności od tego, jak mamy
zaprojektowany backend, ale w większości przypadków zamiast przekazywania całej
informacji na temat projektu, przekazujemy po prostu jego identyfikator.
W takiej sytuacji aplikacja po stronie
backendu po prostu w momencie tworzenia nowego zasobu w postaci użytkownika
przypisuje do niego projekt o identyfikatorze 2, przy okazji jeszcze
sprawdzając, czy w ogóle taka akcja jest możliwa do dokonania.
Jest to kolejny problem dotyczący
security, polegający na tym, że w momencie, gdy nie zadbasz o to, aby
poprawnie zweryfikować to, czy konkretny użytkownik ma prawo do wykonania nie tylko
zapytania typu post na adres users, ale też przypisania do siebie projektu o
identyfikatorze 2, to potencjalnie doprowadzasz do
niebezpiecznej sytuacji polegającej na tym, że ktoś będzie mógł przypisać do
siebie projekt, które nie należy wcale do niego.
Warto o tym pamiętać i na to również
będziemy zwracać uwagę na przestrzeni kolejnych materiałów.
Tymczasem jeżeli chodzi o odpowiedź ze
strony serwera, zwykle wygląda ona tak, że otrzymujemy status odpowiedzi.
I tutaj ponownie jako fuzzy musimy w większości przypadków zadbać o to, aby
odpowiednio go ustawić i też poinformować frontend o tym, co się dokładnie
wydarzyło, a następnie też otrzymujemy informacje na temat rodzaju zwróconych
danych, które w tym przypadku są ponownie obiektem, z tą różnicą, że zamiast po
prostu informacji o tym, że zasób został utworzony, od razu dostajemy pełen.
Użytkownika.
Coś takiego jest niezwykle istotne,
aczkolwiek w niektórych przypadkach może nie być do końca możliwe.
W każdym razie chodzi tutaj o to, że w momencie, gdy tworzymy nowy zasób, bardzo
dobrze jest zaprojektować całość tak, aby od razu dostać pełen obiekt użytkownika.
Tutaj fakt, że rzeczywiście tak się stało
symbolizowane jest identyfikatorem, który został przypisany do tego wpisu w
momencie, gdy został zapisany do bazy danych.
Tak czy inaczej, w momencie gdy mamy tutaj obiekt użytkownika, który został przesłany
nam bezpośrednio z backendu, jesteśmy w stanie precyzyjnie określić, co konkretnie
zostało utworzone i wykorzystać te dane do zaprezentowania ich po stronie frontendu.
I teraz ponownie, pomimo tego, że brzmi to
po pierwsze stosunkowo łatwo, a po drugie jest to oczywiste, tak, z pewnością
niejednokrotnie spotykasz się z API, które po pierwsze nie informuje Cię statusem o
tym, że zasób został utworzony, a po drugie struktura odpowiedzi, którą
otrzymujesz, często wymaga od Ciebie ponownego wysłania zapytania z prośbą o
informację na temat stworzonego przed chwilą zasobu.
Coś takiego po pierwsze jest bardzo niewygodne, a po drugie mało efektywne.
Tutaj chciałbym podkreślić jeden wątek,
który absolutnie potrzebujesz bardzo dobrze zapamiętać.
Mianowicie w momencie, gdy zwracamy tutaj
obiekt użytkownika, to serwer określa w jaki sposób wyglądają dane, które zostały
utworzone i też potem wyświetlane po stronie klienta.
Oznacza to, że tzw.
źródłem prawdy jest tutaj backend, a nie frontend.
Jest to o tyle istotne, że nie dochodzi
tutaj do sytuacji, w których po stronie frontendu wyświetlamy zasadniczo inną
informację niż tą, którą przechowujemy po stronie backendu.
Brak zachowania takiej spójności może
doprowadzić do tego, że użytkownik jest zdezorientowany, a jednocześnie niektóre
błędy po prostu będzie trudno nam naprawić.
Zatem taką złotą regułą jest to, aby
upewnić się, że jedynym źródłem prawdy jest tutaj zawsze backend.
I teraz, jeżeli zastanawiasz się nadal,
dlaczego jest to aż tak bardzo istotne, to chodzi po prostu o to, że po stronie
frontendu nie możesz raczej ufać żadnym informacjom, które się tam znajdują.
Wynika to z faktu, że istnieją proste
sposoby na to, aby modyfikować tym, co znajduje się po stronie frontendu.
Jeżeli nie zabezpieczysz się na taką ewentualność, może dojść do sytuacji, w
której na Twoim serwerze pojawią się informacje, których wcale nie chcesz.
Najprostszym możliwym przykładem jest wagi
dawanie informacji po stronie frontendu i nierobienie tego po stronie backendu.
Nawet jeżeli Twoje importy są odpowiednio zabezpieczone dla użytkownika, tak może
się okazać, że taki użytkownik zmodyfikuje sobie Twój frontend i wyśle do Twojej
aplikacji danych, które nie powinny się tam znaleźć.
Myślę, że w tym momencie możemy zobaczyć jak to działa na przykładzie.
Mam tutaj skonfigurowaną aplikację Fit, w
przypadku której usunąłem już większość początkowego kodu.
Nasze zadanie będzie teraz polegać na tym, aby pobierać informacje na temat
użytkownika, a konkretnie jego imię oraz email.
Te dane pobierzemy za pomocą funkcji, która będzie zwracać obietnice
rozwiązujące się do tablicy zawierającej listę użytkowników.
Poza tym w związku z tym, że wewnątrz jej
wykorzystamy słowo kluczowe, dodajemy tutaj również słowo kluczowe async.
I teraz nie pozostaje już nic innego, jak wykorzystać metodę fetch, z pomocą której
pobierzemy informacje ze wskazanego endpoint.
No i zaraz potem nie pozostaje nic innego jak po prostu wyciągnąć tutaj obiekt
Jameson i tym samym pobrać informacje na temat naszych użytkowników.
Jeżeli teraz uruchomimy nasz serwer to
zobaczymy, że niestety nie mamy tutaj poprawnej odpowiedzi.
Po pierwsze mamy tutaj jakieś nie obsłużone wyjątek, a po drugie od razu
informacja o tym, że zapytanie nie zostało zrealizowane ze względu na to, że nie
jesteśmy upoważnieni do tego, aby je zrealizować.
Sygnalizuje to status 401, który oznacza dokładnie tyle co autorytet.
Wróćmy więc teraz do kodu i zobaczmy, co możemy z tym zrobić.
Pierwszą, najważniejszą zasadą jest to, że musisz pamiętać o tym, aby obsługiwać
ewentualne błędy i przewidywać to, co może się wydarzyć w związku z ich wystąpieniem.
W naszym przypadku na początek możemy
zainteresować ten problem dodając nagłówek odpowiedzialny za uwierzytelnienie tego
połączenia i tym samym jeżeli wrócimy do naszej aplikacji, to tym razem mamy tutaj
listę użytkowników i już na pierwszy rzut oka widzimy, że mamy tutaj pewien problem.
Oczywiście tutaj zaznaczę, że wygenerowane tutaj adresy są całkowicie losowe.
Problemem, które mam na myśli jest fakt, że mamy tutaj bardzo dużą ilość danych,
którą musimy odpowiednio wyświetlić po stronie frontendu.
Teoretycznie nie ma z tym najmniejszego problemu, ponieważ jest tylko 141
rekordów, ale jeżeli tylko mielibyśmy do czynienia z sytuacją, w której rekordy są
nieco bardziej obszerne, bądź jest ich też więcej, to łatwo możemy doprowadzić do
sytuacji, w której nasz frontend i backend zostaje bardzo obciążony i przestaje być
wydajny nawet przy stosunkowo małych liczbach.
Poza tym ponownie z mojego punktu widzenia.
To dość absurdalnie, ale jest to na tyle poważne i często spotykany problem, że
dosłownie kilka tygodni temu napisałem bardzo obszernego maila do jednej z usług,
z których korzystam, w których właśnie opisywałem problemy wynikające z tego, że
w ich przypadku taka sytuacja została zignorowana.
I konkretnie w przypadku mojego konta,
gdzie mam bardzo dużą ilość danych, doszło do sytuacji, w której po prostu nie mogłem
dalej korzystać z aplikacji, ponieważ przeglądarka nie była w stanie odpowiednio
przerobić ich wszystkich po stronie frontendu.
Jest to o tyle ciekawe, że rozwiązanie
tego problemu jest stosunkowo łatwe i oczywiście zastosujemy tutaj mocne
uproszczenie, natomiast chodzi o nic innego jak wykorzystanie paginy.
W tym momencie już niezależnie od tego, czy mamy tam dziesiątki tysięcy rekordów.
I tak początkowo pobieramy tylko pięć, które możemy wyświetlić użytkownikowi i
jeżeli istnieje taka potrzeba po prostu pobierać kolejne porcje.
Zatem jako full stack miej na uwadze
zarówno perspektywę frontendu, gdzie ogólną zasadą jest to, aby pobierać
praktycznie wyłącznie te informacje, które są naprawdę niezbędne, a jednocześnie po
stronie backendu należy zadbać o to, aby przygotować mechanizmy takie jak np.
tagi, nazwa, filtrowanie czy sortowanie.
Do tego, aby umożliwić aplikacji działającej po stronie contentu
odpowiednią konsolę, tego w jaki sposób wyglądają zwrócone informacje.
No ale teraz mam jeszcze kolejny problem z
tym kodem polegający na tym, że obsługujemy teraz tzw.
wesołą ścieżkę.
Przykładowo, jeżeli z jakiegoś powodu będziemy mieć tutaj błędny klucz API,
to oczywiście przy próbie pobrania informacji o użytkownikach zostanie
zwrócony wyjątek, który dodatkowo nie jest poprawnie obsłużony.
Z tego powodu możemy przede wszystkim sobie sprawdzić, czy odpowiedź, którą
otrzymaliśmy od serwera jest oznaczona jako poprawna.
W takiej sytuacji zwracamy obiekt w
postaci Jameson, a w przeciwnym razie wyrzucamy wyjątek.
Już teraz jesteśmy krok dalej, ale
ponownie mamy tutaj do czynienia z nie przesyconym wyjątkiem.
Oznacza to, że w momencie wykonywania naszej funkcji również musimy wykorzystać
cache do tego, aby przechwycić błąd i wyświetlić go użytkownikowi.
Tutaj na potrzeby tego przykładu
wykorzystam konsolę, natomiast produkcyjnie absolutnie tak.
Inaczej przygotuj sobie np.
funkcję umożliwiającą wyświetlenie wiadomości oraz określenie jej rodzaju np.
na błąd. W takiej sytuacji użytkownik jasno
zostanie poinformowany o tym, co się wydarzyło.
Aczkolwiek kolejnym wątkiem, o które trzeba tutaj zadbać, jest też wyświetlenie
mu bardzo jasnej informacji zawierającej detale dotyczące tego, co dokładnie się
wydarzyło oraz przede wszystkim co może w związku z tym zrobić.
W każdym razie, jeżeli ponownie wrócimy do
naszego kodu, to sytuacja się tutaj znacząco zmienia ze względu na to, że
rzeczywiście mamy tutaj poprawnie obsłużony błąd, w przypadku którego już
nie ma problemów, aby wyświetlić go w interfejsie naszej aplikacji.
Na tym jednak problemy się nie kończą, ponieważ nawet jeżeli naprawimy nasz
nagłówek, to w momencie gdy nasz serwer przestanie działać z jakiegoś powodu, to
za każdym razem, gdy użytkownik będzie próbował skorzystać z naszej aplikacji.
Niestety co prawda nasz błąd zostanie tutaj obsłużony, ale informacja o nim nie
będzie w żaden sposób użyteczna dla użytkownika.
Więc tutaj ponownie powinniśmy zastosować
blok, który umożliwi nam dodatkową obsługę błędów.
W takiej sytuacji możemy przenieść cały kod naszej funkcji do tego bloku, a
następnie w momencie wystąpienia błędu, który jest związany z całkowicie błędną
interpretacją zapytania, wyświetlimy stosowny błąd informujący użytkownika, że
nasza aplikacja tymczasowo nie jest dostępna.
Musimy tylko upewnić się jeszcze, że
dodamy tutaj tylko słowo kluczowe wait, ponieważ na wypadek, gdy wystąpią błędy
wewnątrz tej metody, będziemy w stanie je przechwycić z pomocą tego bloku i tym
samym wyrzucić wyjątek, który obsłuży mnie w tym miejscu.
No to teraz jeżeli ostatni raz wrócimy do
naszej aplikacji, to okaże się, że faktycznie poprawna informacja została
tutaj przekazana i ponownie możemy zadbać o to, aby wyświetlić ją użytkownikowi.
Zwróćcie uwagę, że obsługa błędów w takiej sytuacji zdecydowanie bardziej komplikuje
nasz kod i wymaga od nas przewidzenia różnego rodzaju scenariuszy.
I chociażby możemy tutaj rozbudować
obsługę naszych błędów w taki sposób, aby informowały konkretnie użytkownika o tym,
z czego wynika błąd i co może z tym zrobić.
Coś takiego znacząco polepsza komfort
korzystania z naszej aplikacji i też zmniejsza frustrację użytkowników nawet w
sytuacji, gdy nasza usługa z jakiegoś powodu przestaje być aktywna.
Po prostu użytkownik natychmiast jest o tym stosownie poinformowany.
I tutaj naturalnie w związku z tym, że
złożoność naszego kodu w takiej sytuacji rośnie, dobrze jest przygotować sobie
pewną warstwę abstrakcji, która będzie spójna dla wszelkiego rodzaju wykonywanych
zapytań i ewentualnych błędów, które mogą z tego wynikać.
Oczywiście nadal nie unikniemy sytuacji, w której np.
będzie bardziej złożony niż w sytuacji, gdy będziemy podążać
ścieżką, ale jednocześnie szansa na to, że efekt końcowy będzie zdecydowanie lepszy.
Znacząca.
Zatem z tej lekcji zapamiętaj tyle, aby przede wszystkim zwracać uwagę na to, aby
obsługiwać błędy i ewentualne sytuacje, które mogą się wydarzyć.
Oraz oczywiście uwzględnij fakt, że kod,
który mamy tutaj to tylko mały przykład pokazujący to, co można tutaj zrobić.
Natomiast w przypadku produkcyjnej aplikacji będzie konieczne zadbanie o
obsługę błędów w nieco bardziej generycznych sposób.
Tym również będziemy się zajmować na przykładzie aplikacji.
Czy jest.
W związku z tym proszę Cię tutaj jeszcze o cierpliwość.
Drugim wątkiem, które należy bezwzględnie
zapamiętać jest to, aby pobierać informacje w taki sposób, aby zbytnio nie
obciążać aplikacji działającej po stronie klienta.
Chodzi o to, że za każdym razem, gdy pobierasz więcej informacji niż faktycznie
ich potrzebujesz, narażasz się na ryzyko, w którym Twoja zarówno frontend, jak i
backend owa część aplikacji zostanie obciążona i nawet stosunkowo małe liczby
mogą doprowadzić do znacznego spadku wydajności.
Tymczasem jeżeli chodzi o obsługę
komunikacji po stronie frontendu, to tyle, jeżeli chodzi o najważniejsze rzeczy, ale
naturalnie wiele wątków będziemy sobie jeszcze rozszerzać.
Tymczasem dzięki za uwagę i do usłyszenia w kolejnej lekcji.