w Praktyce
10 godz. 44 min · Node.js · Full-stack i Programowanie
Piotr PalarzWeb DeveloperW kursie tym poznasz platformę Node.js od podstaw, aż po bardziej zaawansowane koncepcje. Zaczniemy od omówienia czym jest Node, a także jakie może być zastosowanie tej technologii. Następnie przejdziemy przez proces instalacji i napisanie swojego pierwszego skryptu. Już na samym początku dokładnie omówimy tworzenie własnych modułów, gdyż jest to wiedza niezbędna, by dobrze zrozumieć funkcjonowanie Node. Następnie dowiesz się czym są zdarzenia, jak działa model “publish / subscribe”, a także czym jest “event-driven development”. Chwilę później omówimy pracę z buforami, stream’ami, a także ze standardowym wejściem i wyjściem. Ta wiedza pozwoli Ci zrozumieć jak tworzone aplikacje mogą otrzymywać od użytkownika dane oraz jak je wyświetlają.
Niezwykle ważnym rozdziałem będzie ten, poświęcony pracy z systemem plików. Szczególnie dla dewelopera, pracującego dotychczas z językiem JavaScript wyłącznie w środowisku przeglądarki internetowej. Node pozwala bowiem tworzyć nowe pliki, zapisywać w nich dane oraz odczytywać i usuwać pliki i katalogi. Przy wszystkich tych operacjach, niezwykle ważna jest jednak asynchroniczna natura Node. Dowiesz się jak działa, a także jakie są jej zalety. Na tym etapie nie zabraknie oczywiście praktycznego projektu, którym będzie aplikacja typu CLI (Command Line Interface). Pozwoli nam ona grupowo zmienić nazwy wielu plików, według podanego wzorca.
W kolejnym rozdziale poruszymy fundamentalną dla Node kwestię, mianowicie tworzenie serwerów sieciowych. Zaczniemy od najniższego poziomu, tworząc prosty serwer bazujący na protokole TCP/IP. Wiedza w jaki sposób Node radzi sobie z takim zadaniem, pozwoli później lepiej zrozumieć wyższe warstwy, takie jak np. HTTP czy WebSockets. Chwilę później stworzymy swój pierwszy serwer HTTP, do którego będzie można wysyłać zapytania wprost z przeglądarki internetowej. Omówimy również jak w Node wykorzystać bezpieczne szyfrowanie HTTPS.Na tym etapie będziesz już miał solidną wiedzę jak pracować z Node, jednak zanim przejdziemy dalej, zatrzymamy się, by omówić jak dokładnie działa Node.js, a także jak ta platforma została zbudowana. Dwie dość obszerne lekcje, będą być może jednymi z najważniejszych w tym kursie. Dowiesz się w nich czym jest, a także jak działa jednowątkowa pętla zdarzeń, czym jest proces i wątek, a także zobaczysz kod źródłowy Node.js i wszystkie bloki budulcowe, z jakich Node się składa. To naszym zdaniem niezwykle ważny temat, często jednak pomijany w wielu materiałach. Dzięki dogłębnemu zrozumieniu jednowątkowej natury języka JavaScript i asynchroniczności Node, będziesz mógł tworzyć dużo lepsze aplikacje.
Node.js posiada kilkanaście wbudowanych modułów, z których w dowolnej chwili można skorzystać. Wszystkie jednak dają nam dużą, niskopoziomową kontrolę, ale czasami sporo kodu należy napisać, by zrealizować jakieś zadanie. Jest to jednak świadomy wybór twórców Node, gdyż całą resztę świetnych rozwiązań, dopisuje nieustannie ogólnoświatowa społeczność deweloperów. Zdecydowana większość z modułów ląduje w rejestrze npm. Jest to genialny package manager, który pozwoli nam wyszukiwać, pobierać i aktualizować niezliczoną ilość modułów. Dowiesz się zatem jak korzystać z npm, a chwilę później zaczniemy wykorzystywać zgromadzone tam moduły w dalszej pracy.Jednym z najpopularniejszych modułów jest express.js, który pozwala w bardzo prosty sposób tworzyć serwery HTTP. Grzechem byłoby zatem z niego nie skorzystać. Dowiesz się wszystkiego co niezbędne, by zacząć tworzyć własne aplikacje bazujące na protokole HTTP z użyciem express.js, a także kilku dodatków do tego systemu. Zobaczysz jak routować zapytania, jak korzystać z middleware czy serwować statyczne pliki. Następnie omówimy współpracę z bazą danych MongoDB i z jej wykorzystaniem stworzymy API typu REST. Stworzona aplikacja pozwoli odczytywać dane z bazy i przesyłać je do klienta w formacie JSON, a także dodawać nowe dane, aktualizować i usuwać je. Wszystko to zgodnie z dobrymi praktykami pracy z REST.
Chwilę później czeka Cię kolejny praktyczny projekt - skracacz linków. Stworzymy wspólnie aplikację, która pozwoli skrócić dowolny adres URL do krótkiej formy. Oczywiście będzie działać również w drugą stronę! Kiedy przejdziemy pod skrócony adres, przekieruje nas do odpowiedniej witryny. Node.js to platforma wręcz stworzona do tworzenia aplikacji typu real-time, dlatego w kolejnym rodziale podejmiemy temat technologii WebSockets. Dowiesz się jakie są jej zalety, a także jak pracować z nią po stronie serwera i klienta. Tutaj czeka nas kolejny praktyczny, niezwykle ciekawy projekt. Wykonamy bowiem czat grupowy. Aplikacja ta pozwoli dowolnej ilości użytkowników podłączyć się do czatu podając swój nick, a następnie wysyłać widoczne dla wszystkich wiadomości. Zaimplementujemy nawet takie rozwiązania jak wyświetlanie statusów o dołączeniu kogoś do czatu, a także o jego opuszczeniu.W przedostatnim rodziale tego kursu podejmiemy tematykę dobrych praktyk pracy z Node.js. Na początku omówimy najważniejsze konstrukcje nowej specyfikacji EcmaScript 2015, które są znakomicie wspierane w Node. Chwilę później omówimy jak korzystanie z Promises uprości, a także ulepszy nasz kod. Wśród dobrych praktyk nie zabraknie również informacji o debugowaniu aplikacji. Zobaczysz sprawdzone sposoby, by znaleźć błędy lub lepiej, krok po kroku, zrozumieć jak działa napisany wcześniej kod. Dowiesz się również jak pracować z błędami, by Twoje aplikacje działały w sposób przewidywalny.
Ostatni rozdział w całości został poświęcony temu, co zwykle jest pomijane w innych materiałach, mianowicie wdrażaniu aplikacji do produkcji. Przez cały ten kurs pracować będziemy lokalnie, lecz kiedy aplikacje są już gotowe, wypadałoby udostępnić je światu. Wdrażanie aplikacji napisanych z użyciem Node.js nie jest jednak tak oczywiste, jak np. wgrywanie WordPress’a u wybranego hostingodawcy. Ty będziesz miał jednak możliwość zobaczyć, jak wdrożyć napisany przez nas grupowy czat na platformie Heroku. Jest to bardzo popularny serwis działający jako PaaS (Platform as a Service). Za darmo będziesz mógł w ciągu kilku chwil uruchomić swoją aplikację.Zobaczysz o co należy zadbać, by wszystko poszło gładko. Serwisy typu PaaS dbają o bardzo wiele aspektów wdrażania i serwowania naszych aplikacji, takich jak bezpieczeństwo oraz nieustanną dostępność. Mają jednak pewne ograniczenia. Z tego powodu, dowiesz się również jak wdrożyć swoją aplikację na serwerze wirtualnym VPS z systemem Ubuntu Server. Takie rozwiązanie daje nam całkowitą kontrolę, ale także obarczone jest większą odpowiedzialnością. Zaczniemy od instalacji na serwerze platformy Node.js, systemu kontroli wersji GIT, a także innych niezbędnych modułów
Następnie zobaczysz jak skonfigurować swoje lokalne środowisko tak, by za pomocą GIT’a wysyłać kod do zdalnego serwera, a potem jednym poleceniem wdrażać go do produkcji. Dowiesz się również jak jednocześnie serwować wersję produkcyjną oraz developmencką. W rodziale tym poruszymy również inne kwestie, takie jak procesy potomne czy tworzenie klastrów. Dzięki tej wiedzy, będziesz mógł maksymalnie wykorzystać dostępne zasoby serwera. Na sam koniec tego kursu rzucimy okiem również na inne, nie przedstawione wcześniej zastosowania Node, a także nakreślimy dalszą drogę nauki w tym zakresie.
Kurs ten jest dla wszystkich osób, które dobrze czują się w technologiach frontendowych, tj. HTML, CSS i JavaScript, a teraz chcą rozpocząć swoją przygodę z back-endem. Im zatem lepiej znasz język JavaScript, tym więcej wyciśniesz z Node, natomiast nie jest wymagana bardzo zaawansowana wiedza z zakresu tego języka.
W tej lekcji pokażę ci, w jaki sposób stworzone w lekcji poprzedniej API przenieść na wyższy poziom, tak aby korzystało
z nowoczesnej bazy danych MongoDB.
Do tej pory korzystaliśmy z pliku, w którym wszystko zapisywaliśmy, a teraz będzie to baza danych.
Na początek będę chciał sobie zainstalować moduły, wpisując npm install, a mamy tutaj przykład dokładnie
taki, z jakim skończyliśmy w lekcji poprzedniej. I teraz chcę ci powiedzieć słów kilka o samej bazie danych
MongoDB.
Przejdziemy na stronę tego projektu, którą możesz znaleźć pod adresem mongodb.com.
I to, co jest bardzo ważne, to tę bazę danych możesz sobie bez problemu pobrać za darmo, zainstalować
na Windowsie, Macu czy Linuksie i lokalnie z nią pracować.
Ja pokazywałem, jak to zrobić i jak z taką bazą danych pracować w kursie
Nowoczesne aplikacje webowe z Backbone.js i bardzo serdecznie zapraszam cię do tego kursu.
Natomiast w tym kursie Node nie mamy już niestety czasu, aby omówić dokładnie, jak ta baza danych działa
i jak ją zainstalować i z nią pracować lokalnie, dlatego posłużymy się takim serwisem, który nazywa się
mLab i on udostępnia nam bazy danych MongoDB jako usługę.
W ten sposób nie będziemy jej musieli instalować lokalnie, ale w mLab sobie założymy darmową bazę danych do 500 mb
i będziemy mogli się z nią łączyć i na niej pracować.
Dlatego teraz ważne jest, abyś zarejestrował się na stronie mlab.com, klikając sign up i po rejestracji
powita cię taki ekran, jak ja mam tutaj. Nic więcej nie zrobiłem. Dlatego po rejestracji proszę wróć w
to miejsce.
Zanim jednak utworzymy sobie nową bazę danych, chcę szybko powiedzieć ci, czym jest MongoDB.
Mianowicie jest to baza danych tzw. NoSQL.
A to oznacza, że w przeciwieństwie do baz danych takich jak np. mySQL nie korzysta z języka zapytań SQL.
Jeżeli miałeś do czynienia z mySQL lub z podobnymi bazami danych, to wiesz, że są to relacyjne bazy
danych. One istnieją od dziesięcioleci, natomiast nie zawsze są one idealne we wszystkich zastosowaniach.
Dlatego w ostatnich latach zaczęły powstawać bazy danych NoSQL i zaczęły być coraz bardziej popularne.
Jedną z najpopularniejszych jest właśnie MongoDB.
Różnią się one od relacyjnych baz danych tym, że tam mieliśmy tabele i rekordy oraz relacje pomiędzy
tabelami.
Natomiast tutaj będziemy mieli kolekcje i dokumenty. I to, co jest ważne, w przypadku MongoDB -
takie dokumenty jak zobaczysz, czyli pojedyncze wpisy w bazie danych, to będą po prostu obiekty jsonowe,
z którymi nam, deweloperom JavaScript,
bardzo łatwo jest i intuicyjnie pracować.
Jak to działa w praktyce, zobaczysz za moment.
Natomiast na początek utworzymy nową bazę danych, klikając Create new. I tutaj musimy wybrać dostawcę, a
także region. Wybierzemy sobie może Amazon Web Services i następnie najlepiej Europę, żeby mieć jak najniższy
czas oczekiwania na połączenie z taką bazą danych
później. Czyli mamy tutaj Europa (Irlandia).
I ważne, żeby wybrać Single-node.
I tutaj mamy wersję FREE, czyli szukaj wersji free.
Możesz ją założyć na innym cloud providerze, ale ważne, żeby była to wersja darmowa. Wybierzemy Sandbox i zjedziemy
na sam dół.
No i teraz hiperważne jest to, aby tutaj w Database name nie wpisywać sobie takiej, jaką byś chciał, np. test.
No bo okazuje się, że musi to być nazwa unikalna w ramach całego serwisu. Czyli ktoś jeżeli już użył test, to
nie zadziała.
Dlatego ja wpiszę sobie kurs_node_2, bo wcześniej tworzyłem już bazę danych, która nazywała się kurs_node.
Ty musisz tutaj wpisać jakąś swoją unikalną nazwę.
Może wpisz kurs_node + podkreślnik i nie wiem, twoje imię i nazwisko - cokolwiek, ale aby była ona unikalna.
I teraz wybierzemy Create new MongoDB deployment. W tym miejscu. Chwilę poczekamy i taka baza danych
zostanie dla nas utworzona.
Tak też się stało. Tutaj wyświetla się progres, więc jeszcze momencik musimy poczekać.
Zaraz to się zmieni dokładnie na zielono i będziemy mogli przejść do tej bazy danych, klikając w tym
miejscu. I mówiłem ci, że zamiast tabel i wierszy będziemy mieli kolekcje i dokumenty.
Dokładnie widzimy to w tym miejscu. Nie mamy jeszcze żadnych kolekcji, dlatego będę chciał je utworzyć.
Tutaj kliknę Add collection i nazwiemy ją users, bo pamiętasz być może, że w naszym API korzystaliśmy właśnie
z użytkowników, więc chcę sobie kolekcję nazwać users. Teraz do tej kolekcji będę chciał dodać dokumenty.
Tutaj widzimy, że jest ich 0, dlatego kliknę na users i tutaj jesteśmy w karcie Documents.
Możemy wybrać Add document.
I tutaj pojawi nam się takie okienko, w którym możemy wpisać wersję json tego, co chcemy zapisać w bazie
danych.
Czyli widzisz, że jest to dla nas intuicyjne.
Dlatego ja teraz przejdę do naszej aplikacji, do users, do tego pliku, który mieliśmy, i będę chciał sobie
kilku takich użytkowników dodać. Musimy to zrobić pojedynczo, wklejając ich tutaj.
Natomiast nie dawaj ID, bo chcemy aby ID zostało wygenerowane automatycznie przez MongoDB.
Mogę sobie takiego użytkownika dodać.
Będzie miał name i lastname.
Nie musimy tak jak w przypadku baz danych relacyjnych wcześniej jakby definiować, że dany rekord musi mieć
name czy lastname.
Dowolnie możesz sobie tutaj dodawać dokumenty jsonowe.
Wybierzemy tutaj
Create and continue editing. Jest w porządku. Zauważ, że MongoDB automatycznie dodało _id
i wygląda to w ten sposób. Będziemy za moment z tego korzystać.
Teraz wybiorę Save and go back i przejdziemy do dodania kolejnego dokumentu.
Chciałbym, żebyś to samo zrobił u siebie.
Ja teraz dodam te dokumenty wszystkie, które tutaj mamy bez ID.
I na końcu, żeby nie było tego przecinka, bo będzie błąd. I za sekundę wracam. Ok, dodałem sobie 5 dokumentów,
czyli dokładnie te, które mieliśmy wcześniej w naszym pliku usersDB.
Dlatego ten plik nam już nie będzie potrzebny i ja go tutaj usunę. Przejdziemy do delete.
Plik znika. I wrócimy sobie w to miejsce. Teraz będziemy chcieli nawiązać połączenie z taką bazą danych z poziomu
node.js, czyli naszej aplikacji, i będziemy chcieli wyświetlić sobie te rekordy, które tam się znajdują.
To, co jest bardzo ważne, to dla Node.js mamy oficjalny sterownik MongoDB.
Ja ten sterownik dokładnie omawiam w kursie właśnie wspomnianym wcześniej - Nowoczesne aplikacje webowe
w Backbone.js.
Natomiast ten sterownik jest przynajmniej na początku dosyć skomplikowany w użyciu, a możemy ułatwić
sobie życie, korzystając z takiego ODM-u, który nazywa się Mongoose. I on korzysta pod spodem z tego oficjalnego sterownika
MongoDB dla Node.
Ale oprócz tego opakowuje to wszystko w taki sposób, że dużo, dużo łatwiej jest nam z tym pracować.
Dlatego będziemy chcieli Mongoose sobie zainstalować, wpisując npm install mongoose.
W ten sposób. Save. I teraz będziemy chcieli ten moduł sobie oczywiście zaimportować w odpowiednim pliku.
Nie będzie to potrzebne w tym pliku index.js, ale będziemy pracować w naszym pliku users.js, czyli tutaj.
Tutaj będziemy chcieli sobie to zaimportować.
Fs oraz path już nie będzie nam potrzebne, a także users, które mamy w tym miejscu,
możemy śmiało stąd wyrzucić.
Napiszę const mongoose = require("mongoose"). Ok.
Teraz za pomocą Mongoose będziemy chcieli się podłączyć do naszej bazy danych.
Musimy wrócić na stronę mLab i wrócimy sobie tutaj do db
w moim przypadku kurs_node_2 i będziemy chcieli utworzyć nowego użytkownika. Klikamy tutaj Users i Add
database user. Teraz musimy wybrać nazwę takiego użytkownika. Ja wpiszę sobie Piotr i hasło. W moim przypadku
wpiszę kurs_node.
Powiem tylko tyle, że nie próbuj łączyć się z tą bazą danych, bo w momencie, kiedy oglądasz ten kurs, ja
już ją usunąłem, dlatego mogę ci tutaj śmiało pokazać to hasło. Kurs_node i wybierzemy Create.
Mamy teraz użytkownika, który może się łączyć z taką bazą danych, dlatego teraz z nią będziemy chcieli się
połączyć. I zauważ, że w tym miejscu jest pokazany URL, jak możemy to zrobić. Cały ten URL skopiuję i przejdziemy sobie
teraz tutaj. I na samej górze wpiszemy mongoose.connect. I tutaj taki URL musimy podać. W miejscu gdzie
mamy dbuser i dbpassword, musimy wpisać hasło oraz użytkownika.
Ale ja będę chciał to zrobić dynamicznie, bo w tym kursie jeszcze będziemy mówić o tym, jak można do takiego
procesu wykonywanego w Node przekazywać zmienne środowiskowe i pod tymi zmiennymi możemy mieć właśnie
takie informacje jak hasło czy użytkownika. Aby to na razie zasymulować, to utworzę
sobie tutaj dwie stałe const DB_USER i tutaj wpiszę właśnie Piotr - to co przed momentem utworzyliśmy. I const DB_PASSWORD
i kurs_node. To jest to hasło, które przed momentem na stronie zrobiłem.
I dlatego tutaj korzystam z tego template stringu w ECMAScript 6, żebym mógł sobie to odmienić w ten sposób.
DB_USER i tutaj gdzie dbpassword to podstawimy sobie drugą stałą. Ok.
W ten sposób będziemy mogli z tą bazą danych się połączyć.
A jak wspomniałem, zamiast tworzyć te stałe i tutaj wpisywać te hasła i tak dalej, to to będzie można
przekazać, uruchamiając proces.
Ale o tym będzie później. W ten sposób podłączymy się do takiej bazy danych i będziemy mogli zacząć odbierać
z niej informacje.
Powiem ci od razu, które metody nam już przestaną być potrzebne tutaj.
Przede wszystkim te trzy metody, bo one były po to, aby zapisywać plik. Tak samo findUserById nie
będzie potrzebna.
Zostaną nam tylko te metody, które eksportujemy na dole, czyli właśnie te wszystkie metody do pracy z
API typu REST.
I w nich będziemy chcieli odpowiednio pracować.
Zaczniemy od tego, że tutaj pobieraliśmy sobie poprzez metodę list listę wszystkich użytkowników i wyświetlaliśmy
ją na stronie.
Dlatego będę chciał zacząć od metody, którą mamy tutaj -listUsers i w niej pokazać ci, jak połączyć
się z bazą danych MongoDB i jak z niej wyciągnąć te informacje. Na początek może nodemonem uruchomimy sobie
serwer.
Nie mamy błędów. Mamy. Ok. Nie może znaleźć modułu mongoose.
Widać, że coś źle wpisałem. Tutaj powinno być jeszcze "n". Odświeżmy.
Teraz mamy kolejny błąd. To znaczy, że coś źle wpisałem i poniżej.
Ok. Teraz nie ma błędu. Jest w porządku.
I teraz jeżeli kiedykolwiek pracowałeś ze sterownikiem oficjalnym MongoDB dla Node, np. przerabiając mój
poprzedni kurs, to zobaczysz, jaka jest przewaga Mongoose, który jest ODM-em, czyli Object Data Managerem,
nad tamtym sterownikiem -
jak dużo łatwiej będzie pracować.
Na początek będziemy chcieli sobie utworzyć nowy schemat. Stworzę zmienną schema i odwołamy się do new
mongoose.Schema.
I tutaj sobie podajemy schemat, jaki ma być dla danego modelu. Czyli te dokumenty, które przed momentem
dodawałem do bazy danych, miały name oraz lastname i właśnie to sobie definiujemy tutaj.
Możemy tutaj również definiować funkcje walidujące, czy poprawne dane zostały podane itd.
My natomiast tego nie będziemy robić. Napiszemy name
i tutaj musimy podać typ, czy to będzie number, czy np. string itd.
Więc wpiszemy string.
Zauważ, że nie wpisałem tego tutaj w ten sposób, tylko po prostu przekazałem konstruktor, bo wiemy, że w
JavaScript mamy dostęp do takiej zmiennej globalnej z dużej litery String. I wtedy mongoose będzie wiedziało,
że wszystko ma konwertować na string, co zostanie podane pod name.
Podobnie w naszym przypadku lastname też będzie to string.
Tyle wystarczy. Mamy utworzony nowy schemat, a teraz na bazie tego schematu utworzymy sobie model. Więc napiszemy
User, ale tym razem z dużej litery, bo będzie to jakby konstruktor - zaraz zobaczysz - odwołamy się do mongoose.model,
podamy jego nazwę, napiszę tutaj User i przekażemy sobie schema utworzony wyżej.
Teraz będziemy mogli tworzyć nowe obiekty właśnie tego typu User, a także bezpośrednio korzystać z tego
obiektu dla wyszukiwania elementów.
No i chciałbym zacząć od tego, że wyszukamy sobie wszystkich użytkowników tutaj funkcji listUsers i będziemy
chcieli ich zwrócić.
Od razu jednak chcę ci powiedzieć, że to wywołanie będzie asynchroniczne. Wcześniej mieliśmy synchroniczne wywołania,
czyli mogłem tutaj powiedzieć users i od razu users.list. Zwróciło mi to z tego pliku, który miałem,
i nie było problemu, bo ten plik był wcześniej wczytany do pamięci.
Natomiast teraz będziemy mieli asynchroniczne wywołania, dlatego nasza funkcja, która będzie korzystać z users.list,
musi działać inaczej. I będziemy chcieli taką funkcję sobie przerobić. Czyli users.list
chciałbym, żeby tutaj działało w następujący sposób: users.lists -
będziemy chcieli po prostu pobrać sobie wszystkich użytkowników, kiedy to się uda, to wykonać funkcję
callback, którą tam za moment przekażemy.
Jeżeli będzie jakiś błąd, to chcemy go mieć tutaj. A jeżeli nie, to users. To już znasz, jest to tzw.
error-first callback.
I teraz chciałbym zrobić rzecz następującą. Otóż wytniemy sobie to, co mieliśmy pod spodem.
Nie będę sprawdzał, czy był błąd.
Mógłbym to zrobić, ale tutaj będę chciał przekazać users, którzy zostali mi zwróceni, a jeżeli był błąd, a możemy
to sprawdzić w ten sposób, to chcę przekazać tam pustą tablicę. O tak.
Czyli jeżeli będzie error. to pustą tablicę do widoku przekażemy. Jeżeli nie, to tych użytkowników. Ta funkcja
wykona się później.
Czyli to już nam pokazuje, że users.lists musi przyjąć callback.
Dlatego przejdźmy sobie tutaj i napiszmy cb. To będzie ten callback właśnie do wykonania, cała ta funkcja, którą będziemy
chcieli wykonać.
I teraz wreszcie możemy zacząć pobieranie danych z bazy danych MongoDB.
Jest to bardzo proste.
Otóż odwołamy się do tego, co stworzyliśmy na samej górze, czyli do nowego modelu.
Nawet nie robimy new model czy new user, tylko odwołamy się bezpośrednio do User i następnie możemy napisać
find.
I tutaj musimy podać, co chcemy znaleźć.
Czyli gdybym tutaj np. napisał name równa się Tomasz, to znajdzie nam tylko te obiekty, które miały Tomasza.
Ale my chcemy znaleźć wszystkie, więc podajemy tutaj pusty obiekt. I to wykona się asynchronicznie, więc
musimy podać funkcję, która się wykona później.
Ale robimy to już w metodzie exec. Czyli tutaj jakby przygotowujemy sobie takie query,
tutaj możemy dodawać jeszcze kolejne rzeczy np. where
i tak dalej. Polecam ci na stronie mongoose o tym poczytać.
Bardzo fajne zapytania można tworzyć, a na końcu takiego łańcucha możemy wpisać exec. Ja to zrobię od razu.
I to nam jakby wykona całe takie zapytanie. Czyli wpiszę sobie tutaj taką funkcję. Ona jako pierwszy parametr przyjmuje
błąd, a jako drugi znalezione obiekty, czyli users. Jeżeli będzie błąd - if error, to chcemy wykonać callback,
czyli naszą funkcję przekazaną tutaj właśnie z błędem. Czyli napiszemy cb(err). Natomiast w przeciwnym
wypadku też chcemy wykonać callback, ale jako error przekażemy null, a jako drugi parametr users, bo zostali
znalezieni.
Zobaczysz, że tyle wystarczy. Jeżeli nasz serwer się zresetuje,
przejdziemy sobie tutaj, pod bezpośredni adres, to niestety mamy jakiś błąd. Ok. Widzimy, że users.lists nie jest
funkcją.
Ten błąd jest w pliku index, w linijce 18.
Zobaczmy. Linijka 18, czyli tutaj users.list.
No dokładnie, tutaj popełniłem błąd.
Bez tego "s". Raz jeszcze odświeżmy. I, jak widzisz, wszyscy użytkownicy tutaj się wczytali.
Natomiast oni się teraz wczytali z tej bazy danych MongoDB, która jest gdzieś tam w internecie, ale jak widzisz
wszystko działa poprawnie.
No i teraz jeszcze chcę ci powiedzieć o jednej rzeczy.
Być może to zauważyłeś, być może nie. W jakiś sposób działa nam nasz Mongoose.
Otóż stworzyliśmy sobie nowy model User, ale my nigdzie tutaj nie powiedzieliśmy
tak naprawdę, do jakiej kolekcji chcemy się odwołać, a tutaj utworzyliśmy sobie kolekcję -
chciałbym ci przypomnieć - o nazwie users. Skąd Mongoose o tym wie?
Otóż Mongoose automatycznie, jeżeli tworzysz model o nazwie user, to doda sobie "s" na końcu. Jeżeli stworzyłbyś sobie
np. document, to on doda na końcu "s".
Czyli nazwa kolekcji, bo jest to też dobra praktyka,
to będzie nazwa jakby modelu z "s" na końcu.
Czyli skoro mieliśmy users, a tutaj stworzyłem User, to automatycznie dodało sobie tam "s".
Gdybyś jednak chciał skorzystać ze swojej własnej nazwy kolekcji, to tutaj gdzie definiowaliśmy schema,
można pobrać drugi obiekt z opcjami. I tutaj wpisać collection oraz nazwę takiej kolekcji.
Natomiast w naszym przypadku jest w porządku, bo będzie to po prostu users.
Wszyscy użytkownicy się wyświetlili.
Jak widzisz, nie było żadnego problemu.
Teraz będę chciał ci pokazać, jak możemy resztę naszego API zmodyfikować tak, aby działało poprawnie, używając
właśnie MongoDB.
Więc przejdziemy najpierw do addUser. Przejdźmy tutaj i uzupełnimy to w ten sposób, że będziemy chcieli
utworzyć nowy właśnie model na bazie tego konstruktora User i przekazać mu dane, które są tutaj w userData,
a następnie to wysłać.
Więc jak to zrobimy?
W bardzo prosty sposób. Tworzę nowego użytkownika var user = new User i przekazuję userData, a pamiętasz
z lekcji poprzedniej, że to sobie tutaj przesyłaliśmy. I później chcę go zapisać. Po prostu odwołuję się do user.save,
bo będzie to obiekt, który ma taką metodę, i automatycznie będzie to do poprawnej kolekcji
zapisane.
Czyli nie musimy się łączyć z bazą danych, nie musimy o tym wszystkim myśleć. Mongoose zrobi to za nas i wykona
nam funkcję callback
w zależności od tego, czy uda się wykonać takie zapisanie, czy nie.
Jeżeli nie, to będziemy mieli błąd. Jeżeli się uda, to zwróci nam nowo zapisanego użytkownika razem z jego
ID i jeszcze innymi informacjami.
No i ja chcę znowu sprawdzić sobie - jeżeli był błąd, to wykonać callback z błędem, jeżeli nie, to z użytkownikiem.
Dlatego tutaj chciałbym, żebyśmy przekazywali jeszcze callback.
I teraz przejdziemy tam, gdzie korzystaliśmy z addUser, a być może pamiętasz, gdzie to było. Bo było to
w naszym katalogu api.
Tutaj. Tutaj gdzie mieliśmy post, czyli w tym miejscu. Będziemy musieli sobie to znowu zmodyfikować. W taki
sposób.
Zobacz.
Wydaje się to dużo bardziej skomplikowane i jeszcze w tym kursie to uprościmy. Odwołamy się do users.add.
No i tak jak tutaj napisałem, najpierw userData, potem callback, czyli userData to jest req.body, a callback cała
ta funkcja.
I co ja tutaj chcę zrobić?
Jeżeli będzie błąd, to chcę ustawić res.status na 404, chociaż niekoniecznie w tym przypadku jest to najlepszy
status, kiedy nie uda się takiego użytkownika dodać. Ale żeby zobaczyć listę innych statusów, to przejdźmy
na stronę httpstatuses.com.
I tutaj możesz zobaczyć listę wszystkich status code'ów i możemy tutaj znaleźć być może bardziej odpowiedni.
Natomiast już teraz tego robić nie będziemy, bo w zależności od tego, co się na serwerze wydarzy, to możemy
odpowiedni status odesłać.
My sobie odeślemy 404 i następnie res.json.
Zauważ, że normalny obiekt JavaScript tutaj wstawię, ale zostanie to przez Express odesłane jako json.
Czyli jeżeli się nie uda dodać nowego użytkownika, to wtedy nam się wyświetli właśnie taki komunikat.
Jeżeli się uda, to chcemy go odesłać, a on będzie tutaj przekazany właśnie stąd po dodaniu do bazy danych
MongoDB.
Uruchomimy sobie zatem Postmana i spróbujemy pod users wysłać zapytanie, wcześniej jeszcze api typu post.
W body będziemy chcieli sobie tutaj w raw dodać taki json jak mieliśmy wcześniej. Napiszemy sobie name. W ten sposób.
I powiedzmy, że będzie to Alicja, lastname Kowalczyk i wyślemy. Tyle wystarczy, chociaż jeszcze warto tutaj
dodać w Headers, tak jak mieliśmy wcześniej, content type na application/json. Wyślemy takie zapytanie
i zauważ, co zostało dla nas zwrócone.
Otóż MongoDB dodało sobie do swojej bazy taki obiekt i zwróciło nam jeszcze ten obiekt z takim kluczem v.
To jest wersja, nie będziemy z tego bezpośrednio korzystać. Mongoose sobie z tego korzysta.
I z ID. To ID dla nas będzie ważne.
Zauważ, że ono tutaj zostało dodane automatycznie przez MongoDB i zwrócone.
Gdybyśmy teraz przeszli sobie do przeglądarki i tutaj odświeżyli.
A w zasadzie przeszli pod users.
To zauważ, że tutaj na końcu pojawi nam się właśnie Alicja Kowalczyk, którą dodaliśmy przed momentem, a więc
wszystko działa poprawnie.
Jeszcze raz zaglądając do kodu, udało nam się ją tutaj dodać za pomocą save i została ona zwrócona pod
user.
A to sobie przekazaliśmy do naszego callbacku, który mamy w tym miejscu i odesłaliśmy po prostu jako res.json,
dlatego pojawiło się w Postmanie. Bardzo podobnie będziemy chcieli zrobić z wszystkimi pozostałymi
rzeczami, które tutaj są. Users już wcześniej aktualizowaliśmy, więc widziałeś, że wygląda to w ten sposób.
Ja teraz to szybko uzupełnię i pokażę ci, jak to będzie wyglądać.
Ok. Uzupełniłem wszystko. Jak widzisz, wygląda to praktycznie identycznie, czyli odwołujemy się do naszego
API.
No i po prostu przekazuję odpowiednie informacje, a także funkcję callback. Przeskroluję to, żebyś mógł sobie
to zobaczyć, ewentualnie u siebie przepisać.
Tak to będzie wyglądać.
Czyli już tutaj nic nie tłumaczę, bo nie ma tutaj nic nowego zupełnie.
Natomiast zmiany dokonałem również w pliku users.js, tak abyśmy go mogli zaktualizować, by odpowiednio działał.
No i na początku pokazałem ci, jak dodawać nowego użytkownika.
Otóż korzystamy z new User i następnie user.save.
Natomiast jak pobierać użytkownika?
Mongoose oferuje nam na właśnie tym konstruktorze User
taką metodę, która nazywa się findByID i musimy tam przekazać ID.
No i standardowo później już funkcję callback.
Natomiast w naszym przypadku to już nie będzie ID typu 1 czy 2, ale będzie to ID takie jak MongoDB
przydziela, czyli mogliśmy zobaczyć np. takie ID.
Dlatego zaraz ci pokażę, skąd je weźmiemy. UpdateUser.
Znowu będziemy chcieli tutaj przekazać userData.
Metoda nazywa się findByIdAndUpdate. Bardzo czytelna, bardzo intuicyjna.
No i standardowo callback.
Jeżeli chodzi o usuwanie, findByIdAndRemove. No i znowu standardowo - listUsers zrobiliśmy już wcześniej.
Dlatego teraz będę chciał zrobić jedną dodatkową rzecz w naszym pliku
index - tutaj gdzie pobieraliśmy tych wszystkich użytkowników i przekazywaliśmy ich do widoku.
Przejdźmy do tego widoku views > home. I tutaj gdzie wcześniej wyświetlaliśmy ID,
teraz byłoby to _id,
to będę chciał dodać sobie link.
W zasadzie wkleję to. Zauważ - chcę stworzyć link, który będzie kierował do /user i następnie do tego
właśnie ID.
I tutaj będzie name i lastname.
Więc zobaczmy, jak to będzie wyglądać teraz, po zapisaniu. Przejdziemy do przeglądarki, tutaj - na listę
główną. Pojawiły nam się linki. I zauważ, że po najechaniu mamy np. user i ukośnik itd.
Natomiast jeżeli chcemy przejść pod taki adres, to on nie istnieje.
Dlatego teraz szybko będziemy chcieli go sobie utworzyć.
Czyli tutaj mieliśmy app.get stworzone w ten sposób. Zróbmy sobie app.get("/user/id")
I tutaj będę chciał pobrać takiego jednego użytkownika i wyrenderować odpowiedni widok. Widok nazwiemy sobie
user. Ja tutaj wrzucę od razu gotowy kod.
Zauważ, że metodę get przed momentem sobie stworzyliśmy i ona się tam z tyłu odwoła oczywiście do
findById
w MongoDB i wykona to wszystko.
Jeżeli to jest skomplikowane, to sobie to prześledź po trochu. Jeżeli nie uda nam się znaleźć takiego użytkownika,
to chcę zwrócić status 404. I w Expressie możemy łączyć łańcuchowo takie wywołania, a następnie odesłać
error message.
Nie jest to zawsze dobre rozwiązanie, bo tutaj error będzie zwrócony z bazy danych MongoDB.
Więc niekoniecznie powinniśmy go wyświetlać użytkownikowi na stronie.
Natomiast w tym przypadku robię to po to, aby jeżeli będzie błąd, abyś ty mógł zobaczyć, jaki błąd zwraca
MongoDB. A w przeciwnym wypadku chcę wyrenderować widok user i przekazać mu data, czyli zwróconego
użytkownika.
Ten widok user sobie teraz utworzymy tutaj, w katalogu views szybko. 33/views/user.handlebars. Ja go wkleję. Będzie
on bardzo prosty, po prostu wyświetlimy sobie imię i nazwisko.
No i teraz wróćmy sobie tutaj. Odświeżymy raz jeszcze. Przejdziemy pod taki adres i zauważ, że wszystko działa.
Czyli tutaj mamy listę użytkowników.
Natomiast w momencie kiedy klikam Tomasz Janicki, to przechodzimy pod /user i jego id.
No i co robi Express? Mianowicie Express wtedy wywołuje sobie tę funkcję, sczytując z ID,
no i przekazując je dalej do naszej funkcji users.get, którą sobie wcześniej napisaliśmy. A ona przekaże
to do MongoDB i wszystko zwróci. W ten sposób możemy z tej bazy danych wyświetlać użytkowników.
A chciałbym ci jeszcze przypomnieć, że oczywiście całe nasze API działa.
Jeżeli przejdziemy do Postmana i będziemy mieli id jakiegoś użytkownika, np. tej Alicji, to mogę
wybrać put, wysłać pod user/ właśnie to ID.
W body przekażemy sobie Anna i wyślę. Ok. Pojawił nam się jakiś błąd. Teraz nam się to pojawiło tutaj, więc warto
zajrzeć,
co tam jest nie tak.
Mamy tutaj cb is not defined w pliku users, w 56 linijce. Więc przejdziemy tam, zerkniemy, co może być nie tak.
Dokładnie. Zamiast cb napisałem sobie db. Zobaczmy, czy nie popełniłem tego błędu jeszcze gdzieś
indziej.
Wygląda na to, że nie. Teraz jest w porządku, więc jeszcze raz spróbujmy wysłać takie zapytanie.
Teraz otrzymaliśmy poprawną odpowiedź i z Alicji zrobiliśmy Annę, więc jeżeli teraz przejdziemy z powrotem
do przeglądarki tutaj, odświeżę, to mamy
Anna Kowalczyk, nie Alicja i tutaj również zostało to zaktualizowane.
Natomiast gdybym chciał ją usunąć, to trzeba wysłać zapytanie delete pod ten adres. Z przeglądarki kiedy
klikam tutaj czy wciskam Enter, to wysyłamy get.
Widać to tutaj. Ale wyślijmy sobie delete, bo dlaczego by nie? Wyślemy sobie delete.
To jest dokładnie ten sam adres, więc wysyłamy delete.
Pamiętaj, że tego body przy delete nie musimy przesyłać. Tutaj i tak nie zostanie ono przesłane.
Ono pozostaje w Postmanie po prostu uzupełnione.
Udało się usunąć tego użytkownika i MongoDB nam go zwróciło.
Natomiast jeżeli teraz wrócę do przeglądarki i odświeżę, to mamy tutaj get 200 w tym przypadku.
Nie udało się takiego użytkownika znaleźć, ale powinniśmy tak naprawdę mieć 404.
Wróćmy sobie do edytora Sublime Text.
Zobaczmy, skąd to się wzięło.
Wrócę do index. Tutaj jeżeli błąd to 404.
W przeciwnym wypadku wyrenderowałem.
Natomiast powinniśmy tutaj też dać błąd 404,
jeżeli pod data nie będzie tego użytkownika.
Dlatego najlepiej zrobić sobie console.log i zobaczyć, co jest pod data. Tutaj wyczyścić ekran, odświeżyć.
I pod data jest null. Ok.
Czyli wiedząc, że tam jest null,
możemy i tutaj zrobić status 404.
Bardzo łatwo będzie to zrobić, bo mogę zrobić status i zrobimy sobie coś takiego.
Jeżeli not data, to chcę zwrócić 404, w przeciwnym wypadku 200.
W ten sposób nam ten status powinien się ustawić. Ten console.log możemy wyrzucić.
Czyli widzisz, że jeżeli Mongo nic nie znajdzie, to zwróci po prostu null. Zachowuje się tak samo jak nasze API
z lekcji poprzedniej. Odświeżę i teraz będziemy mieli poprawnie 404.
Przejdźmy sobie wstecz, przejdziemy do Maciej Zieliński.
Mamy 200, więc wszystko działa jak należy.
Jeżeli ta lekcja była za szybko prowadzona, to przepraszam, ale nie chciałem, żeby trwała godzinę.
Jeżeli nie wszystko dokładnie zrozumiałeś, to przerób sobie ją krok po kroku, przepisz ten kod - na pewno zrozumiesz
doskonale, o co tutaj chodzi.
Tym bardziej, że budowaliśmy na bazie API z lekcji poprzedniej.
Jak zatem widzisz, w Node.js możemy łatwo korzystać z baz danych, takich jak MongoDB.
I śmiało polecam ci, abyś zainstalował sobie MongoDB na swoim komputerze i pouczył się, jak z niej korzystać.
A jeżeli jest ci łatwiej, to korzystaj właśnie z takiego serwisu jak mLab,
bo tutaj możesz za darmo sobie taką bazę danych hostować.
Jeśli chodzi o Mongoose, to możesz przejść na stronę tego projektu.
Znajdziesz go pod adresem mongoosejs.com i przejść tutaj do dokumentacji.
Tutaj będziesz mógł zobaczyć dużo przykładów, jak pracować z Mongoose.
Dlatego że my np. nie zrobiliśmy walidacji. Za każdym razem gdy zapisujemy takiego użytkownika do bazy,
mamy to tutaj na samej górze, gdzie jest add.user, to nie sprawdzamy, czy poprawnie zostało wszystko podane
itd.
A tutaj w schema można zdefiniować jeszcze odpowiednie opcje walidacyjne itd, itd.
Do MongoDB jeszcze wrócimy w lekcji kolejnej, gdzie stworzymy praktyczny projekt skracacza linków.
Zapraszam.