Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00067 008914 11221751 na godz. na dobę w sumie
AngularJS. Praktyczne przykłady - ebook/pdf
AngularJS. Praktyczne przykłady - ebook/pdf
Autor: , Liczba stron: 440
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-283-1618-8 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> webmasterstwo >> javascript - programowanie
Porównaj ceny (książka, ebook (-20%), audiobook).

Praktyczne wprowadzenie do AngularJS!

AngularJS to szkielet, który pozwolił tworzyć zaawansowane aplikacje działające w środowisku przeglądarki internetowej. Dał nam do dyspozycji wiele narzędzi, które wcześniej można było zastosować tylko w „tradycyjnych” językach. Wśród nich są zarówno wzorzec MVC (ang. ModelViewController), jak i rozbudowane możliwości testowania. To właśnie dzięki AngularJS możesz wykorzystać w pełni potencjał współczesnych aplikacji internetowych!

Wszyscy programiści od dawna wiedzą, że najlepszym sposobem na nauczenie się nowych narzędzi, języków programowania czy bibliotek jest korzystanie z gotowych przykładów. Właśnie takie podejście do AngularJS dominuje w tej książce. Dzięki niej błyskawicznie opanujesz wszystkie aspekty używania tego szkieletu w codziennej pracy. W kolejnych rozdziałach znajdziesz praktyczne przykłady zastosowania wzorca MVC, wiązania danych, stosowania gotowych dyrektyw oraz usług. Dowiesz się, jak podłączyć się do zasobów serwera dzięki $http oraz utrwalisz dane użytkownika poprzez wprowadzenie warstwy trwałości danych. Na sam koniec zapoznasz się z metodami tworzenia własnych dyrektyw i testowania poszczególnych komponentów aplikacji oraz ze wskazówkami na temat wydajności Twojej aplikacji. Sięgnij po tę książkę, jeżeli chcesz błyskawicznie poznać i wykorzystać w praktyce szkielet AngularJS!

Dzięki tej książce:

Najszybszy sposób na naukę AngularJS!



Chandermani — programista specjalizujący się w tworzeniu aplikacji internetowych. Ma ponad 10 lat doświadczenia w pisaniu aplikacji o różnym stopniu skomplikowania na podstawie rozwiązań firmy Microsoft. Zakochany w AngularJS od pierwszego spotkania. Lider zespołu programistów w Technovert.
Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

Tytuł oryginału: AngularJS by Example Tłumaczenie: Piotr Rajca ISBN: 978-83-283-1615-7 Copyright © Packt Publishing 2015. First published in the English language under the title ‘AngularJS by Example – (9781783553815)’. Polish edition copyright © 2016 by Helion S.A. All rights reserved. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie praw autorskich niniejszej publikacji. Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich właścicieli. Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce. Wydawnictwo HELION ul. Kościuszki 1c, 44-100 GLIWICE tel. 32 231 22 19, 32 230 98 63 e-mail: helion@helion.pl WWW: http://helion.pl (księgarnia internetowa, katalog książek) Pliki z przykładami omawianymi w książce można znaleźć pod adresem: ftp://ftp.helion.pl/przyklady/angupp.zip Drogi Czytelniku! Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres http://helion.pl/user/opinie/angupp Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. Printed in Poland. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Spis tre(cid:258)ci O autorze O recenzentach Przedmowa Zawarto(cid:258)(cid:202) ksi(cid:200)(cid:285)ki Co jest potrzebne? Adresaci ksi(cid:200)(cid:285)ki Konwencje Kod do pobrania Errata Piractwo Rozdzia(cid:239) 1. Pierwsze kroki Podstawy wzorca model – widok – kontroler Zwyczajowa aplikacja Witaj Angular (Odgadnij liczb(cid:218)!) Przygotowywanie roboczego serwera WWW Tworzenie aplikacji Odgadnij liczb(cid:218)! Model aplikacji Kontroler Widok aplikacji Wstawki Dyrektywy Wyra(cid:285)enia Dowi(cid:200)zywanie danych Kontroler po raz wtóry Zasi(cid:218)g Inicjalizacja aplikacji Narz(cid:218)dzia Zasoby Podsumowanie 9 11 13 14 15 15 15 16 17 17 19 20 21 21 22 23 24 25 28 29 30 32 35 36 39 41 41 42 Poleć książkęKup książkę Spis tre(cid:286)ci Rozdzia(cid:239) 2. Piszemy pierwsz(cid:200) aplikacj(cid:218): 7-minutowy trening Czym jest 7-minutowy trening? Pobieranie kodu aplikacji Organizacja kodu Organizacja kodu JavaScriptu Model aplikacji 7-minutowy trening Dodawanie modu(cid:239)ów aplikacji Kontroler aplikacji Wstrzykiwanie zale(cid:285)no(cid:258)ci Implementacja kontrolera Weryfikacja implementacji Implementacja zmiany (cid:202)wiczenia Stosowanie $watch do obserwowania zmian w modelu Zmiana (cid:202)wicze(cid:241) przy u(cid:285)yciu API obietnic Widok aplikacji 7-minutowy trening Stosowanie ng-show do okre(cid:258)lania (cid:258)cie(cid:285)ki do obrazka Stosowanie dyrektywy ng-style i paska post(cid:218)pu frameworku Bootstrap Dodawanie strony pocz(cid:200)tkowej i ko(cid:241)cowej Wprowadzenie od aplikacji jednostronicowych Dostarczanie dodatkowych informacji o (cid:202)wiczeniach Dodawanie paneli opisu i wideo Wy(cid:258)wietlanie pozosta(cid:239)ego czasu treningu przy u(cid:285)yciu filtrów Tworzenie filtra konwertuj(cid:200)cego sekundy na format godzinowy Dodawanie informacji o nast(cid:218)pnym (cid:202)wiczeniu przy u(cid:285)yciu ng-if Podsumowanie Rozdzia(cid:239) 3. Stosowanie kolejnych dobrodziejstw AngularJS Formatowanie instrukcji wykonywania (cid:202)wiczenia Przedstawienie dyrektywy ng-bind-html U(cid:285)ycie ng-bind-html do wy(cid:258)wietlania instrukcji wykonywania (cid:202)wicze(cid:241) (cid:165)ledzenie post(cid:218)pu wykonywania (cid:202)wicze(cid:241) za pomoc(cid:200) klipów audio Implementacja obs(cid:239)ugi audio Wstrzymywanie treningu Implementacja wstrzymywania treningu w kontrolerze WorkoutController Dodawanie fragmentu widoku do wstrzymywania i wznawiania treningu Zatrzymywanie klipów po wstrzymaniu treningu Wstrzymywanie i wznawianie treningu przy u(cid:285)yciu klawiatury Rozbudowa panelu wideo Refaktoryzacja panelu wideo i kontrolera Odtwarzanie wideo w oknie dialogowym Animacje w aplikacjach AngularJS Animacje CSS w AngularJS Animacje JavaScriptu w AngularJS Dodawanie animacji do aplikacji 7-minutowy trening 45 46 47 48 48 51 53 54 55 59 63 65 66 69 72 73 74 75 75 82 82 90 90 94 97 99 101 102 103 105 106 117 118 120 123 124 125 126 127 133 134 136 138 4 Poleć książkęKup książkę Spis tre(cid:286)ci Zapis historii treningu przy u(cid:285)yciu us(cid:239)ug AngularJS Podstawowe informacje o us(cid:239)ugach AngularJS Implementacja zapisu historii treningów Dodawanie widoku historii treningów Zdarzenia w AngularJS Wzbogacanie (cid:258)ledzenia historii przy u(cid:285)yciu zdarze(cid:241) Trwa(cid:239)e przechowywanie danych przy u(cid:285)yciu magazynu przegl(cid:200)darki Filtrowanie historii treningów Filtrowanie i sortowanie z u(cid:285)yciem dyrektywy ng-repeat Podsumowanie Rozdzia(cid:239) 4. Tworzenie aplikacji Mój trening Aplikacja Mój trening — zakres problemu Wymagania aplikacji Mój trening Model aplikacji Mój trening Wspó(cid:239)u(cid:285)ytkowanie modelu treningu Model jako us(cid:239)uga Uk(cid:239)ad aplikacji Mój trening System nawigacyjny aplikacji Mój trening i jej trasy Implementacja list treningów i (cid:202)wicze(cid:241) WorkoutService jako repozytorium danych treningów i (cid:202)wicze(cid:241) Kontrolery list (cid:202)wicze(cid:241) i treningów Widoki list (cid:202)wicze(cid:241) i treningów Tworzenie treningu Tworzenie lewego paska nawigacyjnego Dodawanie us(cid:239)ugi WorkoutBuilderService Dodawanie (cid:202)wicze(cid:241) z poziomu paska nawigacyjnego Implementacja kontrolera WorkoutDetailController Implementacja widoku do tworzenia treningów Obs(cid:239)uga formularzy w AngularJS Dyrektywa form i sprawdzanie poprawno(cid:258)ci formularzy Obiekty zasi(cid:218)gu po raz wtóry Podsumowanie Rozdzia(cid:239) 5. Dodawanie warstwy trwa(cid:239)o(cid:258)ci danych AngularJS i interakcje z serwerem Przygotowanie trwa(cid:239)ego magazynu danych Podstawowe informacje o us(cid:239)udze $http Aplikacja Mój trening i jej integracja z serwerem Wczytywanie danych (cid:202)wicze(cid:241) i treningów Wykonywanie podstawowych operacji na (cid:202)wiczeniach i treningach Us(cid:239)uga $resource Us(cid:239)ugi typu RESTful i ich API Podstawowe informacje o us(cid:239)udze $resource Wyja(cid:258)nienie akcji us(cid:239)ugi $resource Wywo(cid:239)ywanie akcji zasobów Dost(cid:218)p do danych (cid:202)wicze(cid:241) przy u(cid:285)yciu us(cid:239)ugi $resource 141 141 146 149 152 155 157 158 159 163 165 166 167 168 168 169 170 171 174 175 176 176 177 178 179 181 181 185 186 211 221 227 229 230 231 233 236 236 252 259 259 261 262 263 265 5 Poleć książkęKup książkę Spis tre(cid:286)ci Podstawowe operacje z u(cid:285)yciem us(cid:239)ugi $resource Stosowanie us(cid:239)ugi $resource do obs(cid:239)ugi innych rodzajów punktów ko(cid:241)cowych Funkcje przechwytuj(cid:200)ce (cid:285)(cid:200)dania i odpowiedzi Zastosowanie funkcji przechwytuj(cid:200)cej do przekazania klucza API Funkcje przekszta(cid:239)caj(cid:200)ce (cid:285)(cid:200)dania i odpowiedzi Obs(cid:239)uga b(cid:239)(cid:218)dów wyznaczania tras w przypadku odrzucenia obietnicy Obs(cid:239)uga nieodnalezionych treningów Poprawianie aplikacji 7-minutowy trening Podsumowanie Rozdzia(cid:239) 6. Tworzenie i stosowanie dyrektyw Dyrektywy — wprowadzenie Anatomia dyrektyw Tworzenie dyrektywy workout-tile Prezentacja dyrektywy ng-click Tworzenie dyrektywy do zdalnej walidacji nazwy treningu Dyrektywa remote-validator (dla AngularJS 1.3 i starszych) Dyrektywa remote-validator dla Angular 1.3 Aktualizacje modelu z u(cid:285)yciem zdarzenia blur Zastosowanie w(cid:239)a(cid:258)ciwo(cid:258)ci priority do zmiany kolejno(cid:258)ci wykonywania funkcji compile i link Cykl (cid:285)ycia dyrektywy Priorytet a wiele dyrektyw u(cid:285)ytych w tym samym elemencie Implementacja dyrektywy wizualnego wska(cid:283)nika zdalnej walidacji Us(cid:239)uga $compile Funkcja kontrolera dyrektywy Komunikacja mi(cid:218)dzy dyrektywami — integracja wska(cid:283)nika zdalnych operacji i dyrektywy walidacyjnej Wstrzykiwanie kodu HTML w funkcji kompiluj(cid:200)cej dyrektywy Prezentacja szablonów dyrektyw i transkluzji Wyja(cid:258)nienie izolowanego zasi(cid:218)gu dyrektyw Tworzenie dyrektywy przycisku wykonuj(cid:200)cego zdaln(cid:200) operacj(cid:218) Integracja AngularJS i jQuery Integracja wtyczki jQuery Owl Carousel z aplikacj(cid:200) Treningomat Tunelowanie zdarze(cid:241) jQuery przy u(cid:285)yciu dyrektyw Podsumowanie Rozdzia(cid:239) 7. Testowanie aplikacji AngularJS Potrzeba automatyzacji Testowanie w AngularJS Rodzaje testów Kto i kiedy ma testowa(cid:202)? Ekosystem testowy AngularJS Wprowadzenie do tworzenia testów jednostkowych Konfiguracja (cid:258)rodowiska Karma do wykonywania testów jednostkowych Zarz(cid:200)dzanie zale(cid:285)no(cid:258)ciami przy u(cid:285)yciu mened(cid:285)era zale(cid:285)no(cid:258)ci Bower Testy jednostkowe komponentów AngularJS 268 270 271 273 275 277 278 280 280 283 284 285 285 289 292 293 299 301 302 304 306 307 308 310 310 314 315 317 320 325 328 332 335 337 338 338 339 339 340 341 342 344 345 6 Poleć książkęKup książkę Spis tre(cid:286)ci Wprowadzenie do tworzenia testów typu E2E Prezentacja narz(cid:218)dzia Protractor Przygotowywanie (cid:258)rodowiska Protractor do testów E2E Pisanie testów E2E dla naszej aplikacji Przygotowywanie danych na serwerze pod k(cid:200)tem testów E2E Wi(cid:218)cej testów E2E Podsumowanie Rozdzia(cid:239) 8. Obs(cid:239)uga cz(cid:218)sto wyst(cid:218)puj(cid:200)cych scenariuszy Tworzenie nowych aplikacji Projekty startowe Yeoman Tworzenie aplikacji wieloj(cid:218)zycznych (umi(cid:218)dzynarodawianie) Wsparcie dla aplikacji wieloj(cid:218)zycznych w AngularJS Obs(cid:239)uga uwierzytelniania i autoryzacji Uwierzytelnianie w oparciu o cookies Uwierzytelnianie w oparciu o (cid:285)etony Obs(cid:239)uga autoryzacji Wzorce komunikacji i wspó(cid:239)dzielenia danych Stosowanie adresów URL do przekazywania danych pomi(cid:218)dzy stronami Stosowanie obiektów zasi(cid:218)gu Stosowanie us(cid:239)ug Komunikacja mi(cid:218)dzy dyrektywami Stosowanie zdarze(cid:241) Wydajno(cid:258)(cid:202) Wytyczne dotycz(cid:200)ce wydajno(cid:258)ci Przydatne biblioteki dodatkowe Podsumowanie Skorowidz 373 374 375 376 379 381 385 387 388 388 390 392 393 398 399 401 405 408 409 409 411 411 412 413 414 426 427 429 7 Poleć książkęKup książkę Spis tre(cid:286)ci 8 Poleć książkęKup książkę 5 Dodawanie warstwy trwa(cid:239)o(cid:258)ci danych Nadszed(cid:239) czas, by porozmawia(cid:202) z serwerem! Nie ma nic zabawnego w tworzeniu treningu, dodawaniu do niego (cid:202)wicze(cid:241) i zapisywaniu go tylko po to, by pó(cid:283)niej si(cid:218) okaza(cid:239)o, (cid:285)e nasz wysi(cid:239)ek zosta(cid:239) bezpowrotnie stracony, gdy(cid:285) dane nie zosta(cid:239)y nigdzie trwale zapisane. Musimy co(cid:258) z tym zrobi(cid:202). Aplikacje rzadko kiedy stanowi(cid:200) zamkni(cid:218)t(cid:200) ca(cid:239)o(cid:258)(cid:202). Ka(cid:285)da aplikacja konsumencka, niezale(cid:285)nie od swej wielko(cid:258)ci, zawiera fragmenty, które prowadz(cid:200) interakcj(cid:218) z elementami spoza tej apli- kacji. W przypadku aplikacji internetowych te po(cid:239)(cid:200)czenia b(cid:218)d(cid:200) zazwyczaj odwo(cid:239)ywa(cid:202) si(cid:218) do serwera. Aplikacje prowadz(cid:200) interakcj(cid:218) z serwerami, by przeprowadza(cid:202) uwierzytelnianie i auto- ryzacj(cid:218) u(cid:285)ytkowników, zapisywa(cid:202) i pobiera(cid:202) dane, sprawdza(cid:202) ich poprawno(cid:258)(cid:202) oraz wykonywa(cid:202) inne tym podobne operacje. Ten rozdzia(cid:239) przedstawia konstrukcje i mo(cid:285)liwo(cid:258)ci AngularJS zwi(cid:200)zane z komunikacj(cid:200) klient – serwer. W ramach poznawania tych zagadnie(cid:241) zaimplementujemy warstw(cid:218) trwa(cid:239)o(cid:258)ci danych aplikacji Mój trening. Warstwa ta b(cid:218)dzie wczytywa(cid:202) i zapisywa(cid:202) dane (cid:202)wicze(cid:241) i treningów na serwerze. W tym rozdziale omówi(cid:218) nast(cid:218)puj(cid:200)ce zagadnienia: (cid:81) Przygotowanie rozwi(cid:200)zania serwerowego do trwa(cid:239)ego przechowania danych treningu (cid:650) utworzymy konto w serwisie MongoLab i skorzystamy z jego API typu REST, by nawi(cid:200)za(cid:202) z nim po(cid:239)(cid:200)czenie i zapisa(cid:202) w nim dane treningu. (cid:81) Przedstawienie us(cid:239)ugi $http (cid:650) jest to jedna z kluczowych us(cid:239)ug AngularJS i s(cid:239)u(cid:285)y ona do prowadzenia interakcji z serwerami za pomoc(cid:200) protoko(cid:239)u HTTP. Dowiesz si(cid:218), jak jej u(cid:285)ywa(cid:202) do wykonywania wszelkiego rodzaju (cid:285)(cid:200)da(cid:241) HTTP, takich jak GET, POST, PUT oraz DELETE. Poleć książkęKup książkę AngularJS. Praktyczne przyk(cid:225)ady (cid:81) Implementacja, wczytanie i zapisane danych treningu (cid:650) zastosujemy us(cid:239)ug(cid:218) $http, by wczytywa(cid:202) i zapisywa(cid:202) dane treningu w bazie danych MongoLab. (cid:81) Tworzenie i u(cid:285)ywanie obietnic (cid:650) w poprzednich rozdzia(cid:239)ach spotka(cid:239)e(cid:258) si(cid:218) ju(cid:285) z obietnicami. W tym rozdziale nie tylko b(cid:218)dziesz ich u(cid:285)ywa(cid:202) (w ramach obs(cid:239)ugi wywo(cid:239)a(cid:241) HTTP), lecz tak(cid:285)e dowiesz si(cid:218), jak tworzy(cid:202) w(cid:239)asne obietnice i ich u(cid:285)ywa(cid:202). (cid:81) Stosowanie odwo(cid:239)a(cid:241) do innych domen (cid:650) poniewa(cid:285) skorzystamy z serwera MongoLab znajduj(cid:200)cego si(cid:218) w innej domenie, poznasz ograniczenia, jakie przegl(cid:200)darki narzucaj(cid:200) na takie po(cid:239)(cid:200)czenia. Dowiesz si(cid:218) tak(cid:285)e, w jaki sposób techniki JSONP i CORS u(cid:239)atwiaj(cid:200) komunikacj(cid:218) z innymi domenami oraz poznasz wsparcie dla techniki JSONP dost(cid:218)pne w AngularJS. (cid:81) Stosowanie us(cid:239)ugi $resource do tworzenia punktów ko(cid:241)cowych typu RESTful (cid:650) us(cid:239)uga $resource jest abstrakcj(cid:200) utworzon(cid:200) w oparciu o us(cid:239)ug(cid:218) $http i s(cid:239)u(cid:285)(cid:200)c(cid:200) do obs(cid:239)ugi udost(cid:218)pnianych przez serwery punktów ko(cid:241)cowych typu RESTful. Ju(cid:285) wcze(cid:258)niej pozna(cid:239)e(cid:258) t(cid:218) us(cid:239)ug(cid:218) i sposoby jej stosowania. (cid:81) Wczytywanie i zapisywanie (cid:202)wicze(cid:241) przy u(cid:285)yciu us(cid:239)ugi $resource (cid:650) zmodyfikujemy nieco fragmenty naszego systemu, by zastosowa(cid:202) us(cid:239)ug(cid:218) $resource do wczytywania i zapisywania danych (cid:202)wicze(cid:241). (cid:81) Funkcje przechwytuj(cid:200)ce (cid:285)(cid:200)dania i odpowiedzi (cid:650) dowiesz si(cid:218), czym s(cid:200) funkcje przechwytuj(cid:200)ce i jak mo(cid:285)na ich u(cid:285)ywa(cid:202) do przechwytywania wywo(cid:239)a(cid:241) w potokach (cid:285)(cid:200)da(cid:241) i odpowiedzi oraz do modyfikowania sposobu obs(cid:239)ugi zdalnych wywo(cid:239)a(cid:241). (cid:81) Funkcje przekszta(cid:239)caj(cid:200)ce (cid:285)(cid:200)dania i odpowiedzi (cid:650) podobnie jak funkcje przechwytuj(cid:200)ce operuj(cid:200) one na poziomie zawarto(cid:258)ci komunikatów. Poznasz dok(cid:239)adnie ich dzia(cid:239)anie na kilku przyk(cid:239)adach. A zatem zaczynamy! AngularJS i interakcje z serwerem Niemal wszystkie interakcje pomi(cid:218)dzy klientem i serwerem sprowadzaj(cid:200) si(cid:218) zazwyczaj do wysy(cid:239)ania na serwer (cid:285)(cid:200)da(cid:241) HTTP i odbierania przesy(cid:239)anych z niego odpowiedzi. W przypadku aplikacji JavaScriptu komunikacja z serwerem jest zazwyczaj realizowana przy u(cid:285)yciu technologii AJAX. AngularJS udost(cid:218)pnia dwie us(cid:239)ugi s(cid:239)u(cid:285)(cid:200)ce do obs(cid:239)ugi takiej komunikacji: (cid:81) $http (cid:650) to podstawowy komponent frameworku, który s(cid:239)u(cid:285)y do prowadzania interakcji ze zdalnymi serwerami przy u(cid:285)yciu komunikacji bazuj(cid:200)cej na technologii AJAX. Mo(cid:285)na j(cid:200) porówna(cid:202) z funkcj(cid:200) ajax biblioteki jQuery, która dzia(cid:239)a w podobny sposób. (cid:81) $resource (cid:650) ta us(cid:239)uga stanowi abstrakcj(cid:218) utworzon(cid:200) w oparciu o us(cid:239)ug(cid:218) $http, której zadaniem jest u(cid:239)atwianie komunikacji z us(cid:239)ugami typu RESTful (https://pl.wikipedia.org/wiki/Representational_State_Transfer). Zanim jednak zaczniesz szczegó(cid:239)owo poznawa(cid:202) obie powy(cid:285)sze us(cid:239)ugi, musimy przygotowa(cid:202) platform(cid:218) serwerow(cid:200), której b(cid:218)dziemy u(cid:285)ywa(cid:202) do przechowywania danych i zarz(cid:200)dzania nimi. 230 Poleć książkęKup książkę Rozdzia(cid:225) 5. • Dodawanie warstwy trwa(cid:225)o(cid:286)ci danych Przygotowanie trwa(cid:239)ego magazynu danych Do zapewnienia trwa(cid:239)o(cid:258)ci danych wykorzystamy baz(cid:218) danych MongoDB (https://www.mongodb. org/), która s(cid:239)u(cid:285)y do przechowywania dokumentów, przy czym do utworzenia bazy i zarz(cid:200)dzania ni(cid:200) skorzystamy z us(cid:239)ugi MongoLab (https://mongolab.com/). Wybrali(cid:258)my us(cid:239)ug(cid:218) MongoLab, gdy(cid:285) udost(cid:218)pnia ona interfejs pozwalaj(cid:200)cy na prowadzenie bezpo(cid:258)redniej interakcji z baz(cid:200) danych. Dzi(cid:218)ki temu b(cid:218)dziemy mogli unikn(cid:200)(cid:202) instalowania na serwerze dodatkowego opro- gramowania do obs(cid:239)ugi i udost(cid:218)pniania baz danych MongoDB. Udost(cid:218)pnianie magazynu danych b(cid:200)d(cid:283) bazy danych klientom nigdy nie jest dobrym pomys(cid:239)em. Poniewa(cid:285) jednak naszym celem w tej ksi(cid:200)(cid:285)ce jest nauka AngularJS i sposobów prowadzenia komunikacji kilient – serwer, skorzystamy z takiej mo(cid:285)liwo(cid:258)ci i b(cid:218)dziemy korzysta(cid:202) bezpo(cid:258)rednio z bazy MongoDB utworzonej w serwisie MongoLab. Istnieje tak(cid:285)e nowy rodzaj aplikacji, stworzonych w oparciu o rozwi(cid:200)zania typu noBackend. W ich przy- padku programi(cid:258)ci aplikacji klienckich nie wiedz(cid:200), jakie konkretne rozwi(cid:200)zanie serwerowe jest u(cid:285)ywane. Wszelkie interakcje z serwerem ograniczaj(cid:200) si(cid:218) do wywo(cid:239)ywania funkcji API udost(cid:218)pnianych przez serwer. Wi(cid:218)cej informacji na temat rozwi(cid:200)za(cid:241) typu noBackend mo(cid:285)na znale(cid:283)(cid:202) na stronie http://nobackend.org/. Naszym pierwszym zadaniem b(cid:218)dzie za(cid:239)o(cid:285)enie konta w serwisie MongoLab i utworzenie bazy danych. Poni(cid:285)ej opisa(cid:239)em czynno(cid:258)ci, które nale(cid:285)y w tym celu wykona(cid:202): 1. Wejd(cid:283) na stron(cid:218) https://mongolab.com/ i utwórz nowe konto, post(cid:218)puj(cid:200)c zgodnie z wy(cid:258)wietlanymi instrukcjami. 2. Po utworzeniu konta zaloguj si(cid:218) na nie i utwórz now(cid:200) baz(cid:218) danych, klikaj(cid:200)c przycisk Create New umieszczony na stronie g(cid:239)ównej konta. Na kolejnej stronie podaj kilka informacji i ustawie(cid:241) dotycz(cid:200)cych tworzonej bazy danych. Rysunek 5.1 ilustruje, w jaki sposób mo(cid:285)na utworzy(cid:202) bezp(cid:239)atn(cid:200) baz(cid:218) danych i jakie informacje nale(cid:285)y poda(cid:202). 3. Utwórz baz(cid:218) danych i zapisz jej nazw(cid:218). 4. Po utworzeniu bazy danych otwórz j(cid:200), przejd(cid:283) na kart(cid:218) Collection i utwórz dwie kolekcje: (cid:81) exercises (cid:650) do przechowywania dane (cid:202)wicze(cid:241) aplikacji Moj trening; (cid:81) workouts (cid:650) do przechowywania danych treningów. W (cid:258)wiecie MongoDB kolekcje odpowiadaj(cid:200) tabelom baz danych. MongoDB nale(cid:285)y do rodzaju baz danych nazywanych bazami dokumentowymi. W bazach tego typu podstawowymi poj(cid:218)ciami s(cid:200) dokumenty, atrybuty oraz ich wzajemne powi(cid:200)zania. Ponadto, w odró(cid:285)- nieniu od tradycyjnych baz danych, schemat baz MongoDB nie jest sztywny. W tym rozdziale nie b(cid:218)dziemy si(cid:218) zajmowa(cid:202) wyja(cid:258)nianiem, czym s(cid:200) dokumentowe bazy danych ani w jaki sposób nale(cid:285)y opracowa(cid:202) struktur(cid:218) magazynu u(cid:285)ywanego przez nasz(cid:200) aplikacj(cid:218). Aplikacja Mój trening ma niewielkie wymagania, je(cid:258)li chodzi o baz(cid:218) danych, i na jej potrzeby w zupe(cid:239)no(cid:258)ci wystarcz(cid:200) dwie kolekcje dokumentów. W(cid:239)a(cid:258)ciwie nawet nie b(cid:218)dziemy u(cid:285)ywali dokumentowej bazy danych w prawdziwym sensie tego terminu. 231 Poleć książkęKup książkę AngularJS. Praktyczne przyk(cid:225)ady Rysunek 5.1. Tworzenie bezp(cid:239)atnej bazy danych w serwisie MongoLab 5. Po dodaniu kolekcji dodaj konto u(cid:285)ytkownika bazy danych; mo(cid:285)na to zrobi(cid:202) na karcie User. 6. Kolejnym krokiem jest okre(cid:258)lenie klucza API konta MongoLab. Ten klucz b(cid:218)dzie nast(cid:218)pnie dodawany do wszystkich (cid:285)(cid:200)da(cid:241) przesy(cid:239)anych do serwisu MongoLab. Oto, co nale(cid:285)y zrobi(cid:202), by pobra(cid:202) klucz API: 232 Poleć książkęKup książkę Rozdzia(cid:225) 5. • Dodawanie warstwy trwa(cid:225)o(cid:286)ci danych 1. Kliknij nazw(cid:218) u(cid:285)ytkownika (lecz nie nazw(cid:218) konta) wy(cid:258)wietlon(cid:200) w prawym górnym rogu, aby otworzy(cid:202) profil u(cid:285)ytkownika. 2. Skopiuj bie(cid:285)(cid:200)cy klucz API wy(cid:258)wietlony w sekcji API Key. 7. Ostatni(cid:200) czynno(cid:258)ci(cid:200) jest w(cid:239)(cid:200)czenie mo(cid:285)liwo(cid:258)ci korzystania z API typu RESTful zapewniaj(cid:200)cego dost(cid:218)p do danych. W tym celu nale(cid:285)y klikn(cid:200)(cid:202) przycisk Enable Data API access i potwierdzi(cid:202) (cid:285)(cid:200)danie w wy(cid:258)wietlonym oknie dialogowym, klikaj(cid:200)c przycisk Enable. W ten sposób utworzyli(cid:258)my baz(cid:218) danych i jej schemat; teraz musimy zaj(cid:200)(cid:202) si(cid:218) utworzeniem po- cz(cid:200)tkowej zawarto(cid:258)ci naszej bazy. Utworzenie pocz(cid:200)tkowej zawarto(cid:258)ci bazy danych Aplikacja Mój trening zawiera ju(cid:285) domy(cid:258)lny trening sk(cid:239)adaj(cid:200)cy si(cid:218) z 12 (cid:202)wicze(cid:241). Musimy teraz zapisa(cid:202) te dane w bazie danych. W pierwszej kolejno(cid:258)ci otwórzmy plik seed.js dost(cid:218)pny w przyk(cid:239)adach do(cid:239)(cid:200)czonych do ksi(cid:200)(cid:285)ki, w katalogu rozdzial05\punkt_kontrolny_1\app\js. Zawiera on dane treningu i (cid:202)wicze(cid:241) zapisane w formacie JSON oraz szczegó(cid:239)owe instrukcje dotycz(cid:200)ce tego, w jaki sposób nale(cid:285)y je zapisa(cid:202) w bazie danych w serwisie MongoLab. Po wype(cid:239)nieniu danymi pocz(cid:200)tkowymi nasza baza danych b(cid:218)dzie zawiera(cid:202) 1 trening w kolekcji workouts i 12 (cid:202)wicze(cid:241) w kolekcji exercises. Mo(cid:285)na to sprawdzi(cid:202) na stronie MongoLab, kolekcje powinny wygl(cid:200)da(cid:202) jak na rysunku 5.2. Rysunek 5.2. Kolekcje bazy danych po wype(cid:239)nieniu danymi pocz(cid:200)tkowymi Teraz wszystko ju(cid:285) jest przygotowane, mo(cid:285)emy zatem zaj(cid:200)(cid:202) si(cid:218) poznawaniem us(cid:239)ugi $http i implementacj(cid:200) zapewniania trwa(cid:239)o(cid:258)ci danych aplikacji Mój trening. Podstawowe informacje o us(cid:239)udze $http $http jest podstawow(cid:200) us(cid:239)ug(cid:200) AngularJS, która s(cid:239)u(cid:285)y do wykonywania (cid:285)(cid:200)da(cid:241) AJAX. Us(cid:239)uga ta udost(cid:218)pnia interfejs API umo(cid:285)liwiaj(cid:200)cy wykonywanie wszystkich operacji ((cid:285)(cid:200)da(cid:241)) HTTP, takich jak GET, POST, PUT, DELETE i kilka innych. Komunikacja HTTP ma charakter asynchroniczny. Wysy(cid:239)aj(cid:200)c (cid:285)(cid:200)danie HTTP, przegl(cid:200)darka nie czeka na otrzymanie odpowiedzi, tylko zaraz po jego wys(cid:239)aniu kontynuuje przetwarzanie. Oznacza to, (cid:285)e musimy zarejestrowa(cid:202) jak(cid:200)(cid:258) funkcj(cid:218) zwrotn(cid:200), która zostanie wywo(cid:239)ana po otrzy- 233 Poleć książkęKup książkę AngularJS. Praktyczne przyk(cid:225)ady maniu odpowiedzi z serwera. Obietnice (ang. promise) AngularJS i ich API u(cid:239)atwiaj(cid:200) obs(cid:239)ug(cid:218) asynchronicznej komunikacji i s(cid:200) powszechnie u(cid:285)ywane wraz z us(cid:239)ug(cid:200) $http, o czym si(cid:218) nie- bawem przekonasz. Poni(cid:285)szy przyk(cid:239)ad przedstawia podstawow(cid:200) sk(cid:239)adni(cid:218) us(cid:239)ugi $http: $http(config) Wywo(cid:239)anie us(cid:239)ugi wymaga przekazania obiektu konfiguracyjnego i zwraca obietnic(cid:218). Obiekt config zawiera zestaw w(cid:239)a(cid:258)ciwo(cid:258)ci okre(cid:258)laj(cid:200)cych posta(cid:202) i sposób wykonania (cid:285)(cid:200)dania. W(cid:239)a(cid:258)ci- wo(cid:258)ci te okre(cid:258)laj(cid:200) mi(cid:218)dzy innymi typ operacji HTTP (GET, POST, PUT itd.), adres URL zdalnego serwera, parametry (cid:239)a(cid:241)cucha zapytania i wysy(cid:239)ane nag(cid:239)ówki. Wszelkie szczegó(cid:239)owe informacje dotycz(cid:200)ce opcji konfiguracyjnych us(cid:239)ugi $http s(cid:200) dost(cid:218)pne w jej dokumentacji, na stronie https://code.angularjs.org/1.3.3/docs/api/ng/service/$http. W dal- szej cz(cid:218)(cid:258)ci rozdzia(cid:239)u, podczas prac nad implementacj(cid:200) aplikacji, skorzystamy z kilku tych opcji. Wywo(cid:239)anie us(cid:239)ugi $http zwraca obiekt obietnicy. Oprócz standardowych funkcji tworz(cid:200)cych API obietnic (takich jak then) ten obiekt zawiera tak(cid:285)e dwie dodatkowe funkcje zwrotne, success i error, które s(cid:200) wywo(cid:239)ywane zale(cid:285)nie od tego, czy (cid:285)(cid:200)danie HTTP zako(cid:241)czy(cid:239)o si(cid:218) pomy(cid:258)lnie, czy te(cid:285) w trakcie jego wykonywania wyst(cid:200)pi(cid:239)y b(cid:239)(cid:218)dy. Oto podstawowy sposób wykonywania (cid:285)(cid:200)da(cid:241) HTTP przy u(cid:285)yciu us(cid:239)ugi $http: $http({method: GET , url: /endpoint }). success(function(data, status, headers, config) { // wywo(cid:225)ywana, gdy (cid:298)(cid:261)danie zostanie wykonane prawid(cid:225)owo }). error(function(error, status, headers, config) { // wywo(cid:225)ywana, gdy podczas wykonywania (cid:298)(cid:261)dania wyst(cid:261)pi(cid:261) b(cid:225)(cid:266)dy // parametr error zawiera przyczyn(cid:266) problemu }); Powy(cid:285)szy kod przesy(cid:239)a (cid:285)(cid:200)danie HTTP pod adres /endpoint, a pó(cid:283)niej, kiedy odpowied(cid:283) jest ju(cid:285) dost(cid:218)pna, wywo(cid:239)uje albo funkcj(cid:218) zwrotn(cid:200) success, albo error. Odpowiedzi HTTP o kodach z zakresu od 200 do 299 s(cid:200) uznawane za prawid(cid:239)owe. Odpowiedzi o kodach 40x i 50x s(cid:200) traktowane jako b(cid:239)(cid:218)dy i powoduj(cid:200) wywo(cid:239)anie funkcji zwrotnej error. Funkcje zwrotne success i error maj(cid:200) cztery parametry: (cid:81) data lub error (cid:650) zawiera odpowied(cid:283) zwrócon(cid:200) przez serwer, mog(cid:200) to by(cid:202) dane lub, w przypadku (cid:285)(cid:200)dania zako(cid:241)czonego niepowodzeniem, informacje o b(cid:239)(cid:218)dzie. (cid:81) status (cid:650) zawiera kod statusu odpowiedzi HTTP. (cid:81) headers (cid:650) zawiera nag(cid:239)ówki odpowiedzi HTTP. (cid:81) config (cid:650) zawiera obiekt konfiguracyjny przekazany w wywo(cid:239)aniu us(cid:239)ugi $http. 234 Poleć książkęKup książkę Rozdzia(cid:225) 5. • Dodawanie warstwy trwa(cid:225)o(cid:286)ci danych W przypadku (cid:285)(cid:200)da(cid:241) AJAX przedstawiona powy(cid:285)ej sk(cid:239)adnia us(cid:239)ugi $http jest stosowana bar- dzo rzadko. Us(cid:239)uga ta udost(cid:218)pnia grup(cid:218) metod pomocniczych, upraszczaj(cid:200)cych generowanie konkretnych typów (cid:285)(cid:200)da(cid:241) HTTP. Mo(cid:285)na do niej zaliczy(cid:202) nast(cid:218)puj(cid:200)ce metody: (cid:81) $http.get(url, [config]), (cid:81) $http.post(url, data, [config]), (cid:81) $http.put(url, data, [config]), (cid:81) $http.delete(url, [config]), (cid:81) $http.head(url, [config]), (cid:81) $http.jsonp(url, [config]). W wywo(cid:239)aniach ka(cid:285)dej z tych funkcji mo(cid:285)na przekaza(cid:202) (jako ostatni argument) ten sam (opcjo- nalny) obiekt config. Interesuj(cid:200)cym aspektem standardowej konfiguracji us(cid:239)ugi $http jest to, (cid:285)e zapewnia ona bardzo (cid:239)atw(cid:200) obs(cid:239)ug(cid:218) danych w formacie JSON. Oto jej najwa(cid:285)niejsze efekty: (cid:81) W przypadku operacji GET, je(cid:258)li odpowied(cid:283) zawiera dane w formacie JSON, to framework automatycznie przetworzy przekazane dane w formie (cid:239)a(cid:241)cuchowej na obiekt JavaScriptu. W efekcie pierwszy parametr funkcji zwrotnej success (data) b(cid:218)dzie zawiera(cid:239) nie (cid:239)a(cid:241)cuch znaków, lecz obiekt JavaScriptu. (cid:81) W przypadku wykonywania (cid:285)(cid:200)da(cid:241) POST lub PUT obiekty s(cid:200) automatycznie serializowane, a przed wys(cid:239)aniem (cid:285)(cid:200)dania okre(cid:258)lana jest odpowiednia warto(cid:258)(cid:202) nag(cid:239)ówka typu zawarto(cid:258)ci (Content-Type: application/json). Czy to oznacza, (cid:285)e us(cid:239)uga $http nie potrafi obs(cid:239)ugiwa(cid:202) danych w innych formatach? Absolutnie nie. $http jest us(cid:239)ug(cid:200) o charakterze ogólnym, która generuje (cid:285)(cid:200)dania AJAX i mo(cid:285)e obs(cid:239)ugiwa(cid:202) dowolne formaty (cid:285)(cid:200)da(cid:241) i odpowiedzi. Ka(cid:285)de (cid:285)(cid:200)danie AJAX w AngularJS jest wykonywane przy u(cid:285)yciu us(cid:239)ugi $http — bezpo(cid:258)rednio lub po(cid:258)rednio. Na przyk(cid:239)ad zdalne widoki wczytywane za pomoc(cid:200) dyrektyw ng-view lub ng-include w niewidoczny dla nas sposób korzystaj(cid:200) w(cid:239)a(cid:258)nie z us(cid:239)ugi $http. Warto zajrze(cid:202) do przyk(cid:239)adu opublikowanego w serwisie jsFiddle na stronie http://jsfiddle.net/cmyworld/ doLhmgL6/, który przedstawia zastosowanie us(cid:239)ugi $http do przesy(cid:239)ania na serwer danych w formacie tradycyjnie u(cid:285)ywamy przez formularze HTML korzystaj(cid:200)ce z metody POST ( Content-Type : application/ x-www-form-urlencoded ). To wy(cid:239)(cid:200)cznie AngularJS sprawia, (cid:285)e korzystanie z danych w formacie JSON jest tak (cid:239)atwe, elimi- nuj(cid:200)c konieczno(cid:258)(cid:202) pisania powtarzaj(cid:200)cej si(cid:218) logiki serializacji i deserializacji oraz ustawiania od- powiednich nag(cid:239)ówków HTTP, których zazwyczaj wymaga obs(cid:239)uga danych w formacie JSON. Dysponuj(cid:200)c ju(cid:285) podstawow(cid:200) znajomo(cid:258)ci(cid:200) us(cid:239)ugi $http, mo(cid:285)emy jej u(cid:285)y(cid:202) do zaimplementowania czego(cid:258) u(cid:285)ytecznego. Spróbujmy zatem zapewni(cid:202) trwa(cid:239)o(cid:258)(cid:202) danych w naszej aplikacji. 235 Poleć książkęKup książkę AngularJS. Praktyczne przyk(cid:225)ady Aplikacja Mój trening i jej integracja z serwerem Zgodnie z informacjami podanymi w poprzednim podrozdziale wszelkie interakcje klient – serwer maj(cid:200) charakter asynchroniczny. Rozwi(cid:200)zanie to stanie si(cid:218) bardziej zrozumia(cid:239)e, kiedy zmo- dyfikujemy aplikacj(cid:218) Mój trening tak, by wczytywa(cid:239)a dane z serwera. W poprzednim rozdziale zbiór domy(cid:258)lnych (cid:202)wicze(cid:241) i jeden trening zosta(cid:239)y na sta(cid:239)e zakodowane w implementacji us(cid:239)ugi WorkoutService. Przekonajmy si(cid:218), w jaki sposób mo(cid:285)na je wczyta(cid:202) z serwera. Wczytywanie danych (cid:202)wicze(cid:241) i treningów Na pocz(cid:200)tku tego rozdzia(cid:239)u zapisali(cid:258)my w bazie danych informacje z pliku seed.js. Teraz zale(cid:285)y nam na tym, by w jaki(cid:258) sposób wy(cid:258)wietli(cid:202) te dane w widokach aplikacji. Zastosujemy do tego REST API us(cid:239)ugi MongoLab. REST API serwisu MongoLab korzysta z klucza API do autoryzacji wszystkich (cid:285)(cid:200)da(cid:241). Ka(cid:285)de (cid:285)(cid:200)danie kie- rowane do punktów ko(cid:241)cowych MongoLab musi zawiera(cid:202) w (cid:239)a(cid:241)cuchu zapytania parametr o postaci apikey= klucz , gdzie klucz to klucz API u(cid:285)ytkownika serwisu odczytany podczas przygotowy- wania bazy zgodnie z informacjami podanymi we wcze(cid:258)niejszej cz(cid:218)(cid:258)ci rozdzia(cid:239)u. Trzeba pami(cid:218)ta(cid:202), (cid:285)e ten klucz jest zawsze skojarzony z kontem u(cid:285)ytkownika. dlatego nie nale(cid:285)y udost(cid:218)pnia(cid:202) go innym osobom. API MongoLab zapewnia mo(cid:285)liwo(cid:258)(cid:202) przegl(cid:200)dania i aktualizacji danych przy u(cid:285)yciu adresów o przewidywalnej postaci. Poni(cid:285)ej przedstawiam typowe wzorce dost(cid:218)pu do punktów ko(cid:241)cowych dowolnych kolekcji MongoDB (zak(cid:239)adaj(cid:200)c, (cid:285)e adres URL bazy danych ma posta(cid:202) https://api. mongolab.com/api/1/databases): (cid:81) bazadanych /collections/ nazwa ?apiKey= klucz (cid:650) udost(cid:218)pnia dwa typy (cid:285)(cid:200)da(cid:241): (cid:81) GET (cid:650) pobiera wszystkie obiekty dost(cid:218)pne w kolekcji o podanej nazwie. (cid:81) POST (cid:650) dodaje nowy obiekt do kolekcji o podanej nazwie. MongoLab u(cid:285)ywa w(cid:239)a(cid:258)ciwo(cid:258)ci _id w celu unikalnej identyfikacji dokumentów (obiektów). Je(cid:258)li przes(cid:239)ane dane nie b(cid:218)d(cid:200) zawiera(cid:202) tej w(cid:239)a(cid:258)ciwo(cid:258)ci, to zostanie ona wygenerowana automatycznie. (cid:81) bazadanych /collections/ nazwa / id ?apiKey= klucz (cid:650) udost(cid:218)pnia trzy typy (cid:285)(cid:200)da(cid:241): (cid:81) GET (cid:650) pobiera z kolekcji o podanej nazwie konkretny dokument (element kolekcji) okre(cid:258)lony za pomoc(cid:200) identyfikatora (id, który b(cid:218)dzie dopasowywany do w(cid:239)a(cid:258)ciwo(cid:258)ci _id). (cid:81) PUT (cid:650) aktualizuje okre(cid:258)lony element (id) kolekcji o podanej nazwie. (cid:81) DELETE (cid:650) usuwa z kolekcji o podanej nazwie element o okre(cid:258)lonym identyfikatorze (id). 236 Poleć książkęKup książkę Rozdzia(cid:225) 5. • Dodawanie warstwy trwa(cid:225)o(cid:286)ci danych Szczegó(cid:239)owe informacje na temat interfejsu REST API mo(cid:285)na znale(cid:283)(cid:202) w dokumentacji serwisu MongoLab, na stronie http://docs.mongolab.com/data-api/. Teraz nic ju(cid:285) nie stoi na przeszkodzie, by(cid:258)my zaj(cid:218)li si(cid:218) implementacj(cid:200) stron z listami (cid:202)wicze(cid:241) i treningów. Zanim zaczniemy, nale(cid:285)y skopiowa(cid:202) z przyk(cid:239)adów do(cid:239)(cid:200)czonych do ksi(cid:200)(cid:285)ki dzia(cid:239)aj(cid:200)c(cid:200) wersj(cid:218) aplikacji Mój trening, dost(cid:218)pn(cid:200) w katalogu rozdzial04\punkt_kontrolny_7. Jest to pe(cid:239)na wersja aplikacji zawieraj(cid:200)ca tak(cid:285)e dzia(cid:239)aj(cid:200)cy formularz do tworzenia i edycji (cid:202)wicze(cid:241), który mieli(cid:258)my zaimplementowa(cid:202) samodzielnie, w ramach (cid:202)wiczenia. Wczytywanie list (cid:202)wicze(cid:241) i treningów z serwera Aby pobra(cid:202) listy (cid:202)wicze(cid:241) i treningów z bazy danych w serwisie MongoLab, musimy zmodyfikowa(cid:202) dwie metody us(cid:239)ugi WorkoutService — getExercises i getWorkouts. Poni(cid:285)ej przedstawiam zmiany, które nale(cid:285)y wprowadzi(cid:202) w kodzie metody getExercises, w pliku services.js umieszczonym w katalogu app\js\shared: service.getExercises = function () { var collectionsUrl = https://api.mongolab.com/api/1/databases/ nazwa /collections ; return $http.get(collectionsUrl + /exercises , { params: { apiKey: klucz } }); }; W powy(cid:285)szym kodzie fragmenty nazwa i klucz nale(cid:285)y zast(cid:200)pi(cid:202) odpowiednio nazw(cid:200) bazy danych w serwisie MongoLab i kluczem API. Ponadto koniecznie nale(cid:285)y pami(cid:218)ta(cid:202) o dodaniu do deklaracji us(cid:239)ugi WorkoutService zale(cid:285)no(cid:258)ci od us(cid:239)ugi $http. Powy(cid:285)sza, zmodyfikowana wersja funkcji tworzy adres URL odwo(cid:239)uj(cid:200)cy si(cid:218) do serwisu MongoLab, a nast(cid:218)pnie wywo(cid:239)uje funkcj(cid:218) $http.get, by pobra(cid:202) list(cid:218) (cid:202)wicze(cid:241). Pierwszym argumentem jej wywo(cid:239)ania jest adres URL, na jaki nale(cid:285)y wys(cid:239)a(cid:202) (cid:285)(cid:200)danie, a drugim obiekt konfiguracyjny (config). W(cid:239)a(cid:258)ciwo(cid:258)(cid:202) params obiektu konfiguracyjnego zapewnia mo(cid:285)liwo(cid:258)(cid:202) dodawania do adresu URL parametrów (cid:239)a(cid:241)cucha zapytania. W naszym przypadku parametrem tym b(cid:218)dzie klucz API (?apiKey=98dkdd) zapewniaj(cid:200)cy dost(cid:218)p do API MongoLab. Ta nowa wersja funkcji getExercises zwraca obietnic(cid:218), a zatem musimy zmodyfikowa(cid:202) kod, który jej u(cid:285)ywa. 237 Poleć książkęKup książkę AngularJS. Praktyczne przyk(cid:225)ady W tym celu musimy otworzy(cid:202) plik exercise.js znajduj(cid:200)cy si(cid:218) w katalogu WorkoutBuilder i zmo- dyfikowa(cid:202) kontroler ExerciseListController, a konkretnie zast(cid:200)pi(cid:202) istniej(cid:200)c(cid:200) implementacj(cid:218) funkcji init (kod umieszczony wewn(cid:200)trz niej) poni(cid:285)sz(cid:200) instrukcj(cid:200): WorkoutService.getExercises().success(function (data) { $scope.exercises = data; }); Zastosowali(cid:258)my w niej funkcj(cid:218) zwrotn(cid:200) success obietnicy, by dowi(cid:200)za(cid:202) list(cid:218) (cid:202)wicze(cid:241) do kon- trolera. Powy(cid:285)szy kod wyra(cid:283)nie pokazuje asynchroniczne dzia(cid:239)anie us(cid:239)ugi $http i obietnic, gdy(cid:285) dane (cid:202)wicze(cid:241) s(cid:200) zapisywane we w(cid:239)a(cid:258)ciwo(cid:258)ci exercises w funkcji zwrotnej wywo(cid:239)ywanej dopiero po odebraniu odpowiedzi z serwera. Spróbujmy teraz wy(cid:258)wietli(cid:202) stron(cid:218) z list(cid:200) (cid:202)wicze(cid:241) w przegl(cid:200)darce (#/builder/exercises) i upewni(cid:202) si(cid:218), (cid:285)e zostanie ona wczytana z serwera. Lista (cid:285)(cid:200)da(cid:241) sieciowych wykonanych przez przegl(cid:200)dark(cid:218) powinna zawiera(cid:202) pozycje takie jak na rysunku 5.3. Rysunek 5.3. (cid:191)(cid:200)dania pobieraj(cid:200)ce dane z serwera MongoLab Jak wida(cid:202), (cid:202)wiczenia s(cid:200) wczytywane prawid(cid:239)owo. A co z treningami? Wczytywanie listy treningów mo(cid:285)na poprawi(cid:202) w podobny sposób. Zmodyfikujmy zatem funkcj(cid:218) getWorkouts w us(cid:239)udze WorkoutService tak, by wyczytywa(cid:239)a dane z serwera. Implementacja tej funkcji b(cid:218)dzie bardzo podobna do implementacji funkcji get (cid:180)Exercises, z t(cid:200) ró(cid:285)nic(cid:200), (cid:285)e adres URL b(cid:218)dzie si(cid:218) odwo(cid:239)ywa(cid:239) do kolekcji o nazwie workouts. Nast(cid:218)pnie musimy tak(cid:285)e zmodyfikowa(cid:202) funkcj(cid:218) init kontrolera WorkoutListController, analogicznie jak wcze(cid:258)niej zmodyfikowali(cid:258)my funkcj(cid:218) init us(cid:239)ugi ExerciseListController. To by(cid:239)o (cid:239)atwe! Tak samo mo(cid:285)emy poprawi(cid:202) wszystkie pozosta(cid:239)e fragmenty aplikacji pobieraj(cid:200)ce dane treningów i (cid:202)wicze(cid:241). Niemniej zanim to zrobimy, warto zwróci(cid:202) uwag(cid:218), (cid:285)e wci(cid:200)(cid:285) mo(cid:285)na poprawi(cid:202) implementacj(cid:218) aplikacji. Pierwszym problemem zwi(cid:200)zanym z aktualn(cid:200) implementacj(cid:200) funkcji getExercises i getWorkouts jest to, (cid:285)e nazwa bazy danych i klucz API s(cid:200) podane na sta(cid:239)e w kodzie, co w przysz(cid:239)o(cid:258)ci mo(cid:285)e utrudni(cid:202) jego utrzymanie. Optymalnym rozwi(cid:200)zaniem b(cid:218)dzie wstrzykni(cid:218)cie tych warto(cid:258)ci do us(cid:239)ugi WorkoutService. Bazuj(cid:200)c na zdobytej wcze(cid:258)niej wiedzy i znajomo(cid:258)ci AngularJS, wiemy, (cid:285)e gdyby WorkoutService by(cid:239)a us(cid:239)ug(cid:200) typu provider, to mogliby(cid:258)my przekaza(cid:202) do niej dane konfiguracyjne niezb(cid:218)dne do odpowiedniego przygotowania us(cid:239)ugi na etapie (cid:239)adowania aplikacji. To rozwi(cid:200)zanie pozwoli(cid:239)oby nam skonfigurowa(cid:202) us(cid:239)ug(cid:218) przed jej u(cid:285)yciem. Nadszed(cid:239) zatem czas, by zastosowa(cid:202) t(cid:218) teori(cid:218) w praktyce! 238 Poleć książkęKup książkę Rozdzia(cid:225) 5. • Dodawanie warstwy trwa(cid:225)o(cid:286)ci danych Implementacja dostawcy us(cid:239)ugi WorkoutService Implementacja us(cid:239)ugi WorkoutService w formie dostawcy pozwoli nam okre(cid:258)li(cid:202) u(cid:285)ywane przez ni(cid:200) informacje — nazw(cid:218) bazy danych i klucz API — na etapie konfiguracji. Skopiujmy zatem definicj(cid:218) us(cid:239)ugi WorkoutService z pliku services.js dost(cid:218)pnego w przyk(cid:239)adach do(cid:239)(cid:200)czonych do ksi(cid:200)(cid:285)ki, w katalogu rozdzial05\punkt_kontrolny_1\app\js\shared, i wklejmy go do analogicznego pliku w tworzonej aplikacji. W ten sposób zamienimy wcze(cid:258)niejsz(cid:200) us(cid:239)ug(cid:218) na us(cid:239)ug(cid:218) typu provider. Nowa wersja us(cid:239)ugi definiuje metod(cid:218) configure, odpowiadaj(cid:200)c(cid:200) za okre(cid:258)lenie nazwy bazy danych i klucza API oraz przygotowanie adresu URL po(cid:239)(cid:200)czenia. Oto jej kod: this.configure = function (dbName, key) { database = database; apiKey = key; collectionsUrl = apiUrl + dbName + /collections ; } Usun(cid:218)li(cid:258)my tak(cid:285)e funkcje setupInitialExercises, setupInitialWorkouts oraz init, gdy(cid:285) dane b(cid:218)d(cid:200) teraz pobierane z serwera MongoLab. Zmienili(cid:258)my równie(cid:285) implementacje funkcji getExercises i getWorkouts tak, by korzysta(cid:239)y z przygotowanych wcze(cid:258)niej parametrów: service.getExercises = function () { return $http.get(collectionsUrl + /exercises , { params: { apiKey: apiKey } }); }; I w ko(cid:241)cu utworzenie obiektu service zosta(cid:239)o przeniesione do funkcji $get dostawcy. $get jest funkcj(cid:200) wytwórcz(cid:200) odpowiedzialn(cid:200) za utworzenie w(cid:239)a(cid:258)ciwej us(cid:239)ugi. Kolejn(cid:200) czynno(cid:258)ci(cid:200) b(cid:218)dzie zmodyfikowanie funkcji config modu(cid:239)u app i wstrzykni(cid:218)cie konfi- guracji serwera MongoLab do nowej implementacji us(cid:239)ugi WorkoutService (za pomoc(cid:200) Workout (cid:180)ServiceProvider). Otwórzmy zatem plik app.js i w definicji funkcji config dodajmy do ju(cid:285) istniej(cid:200)cej listy do- stawców zale(cid:285)no(cid:258)(cid:202) od dostawcy WorkoutServiceProvider. Ponadto w kodzie tej funkcji musi- my doda(cid:202) wywo(cid:239)anie metody configure tego dostawcy, okre(cid:258)laj(cid:200)ce nazw(cid:218) u(cid:285)ywanej bazy da- nych i klucz API: WorkoutServiceProvider.configure( mojaBaza , mójKluczAPI ); Ta nowa implementacja us(cid:239)ugi WorkoutService jest znaczenie lepsza od poprzedniej, poniewa(cid:285) zapewnia mo(cid:285)liwo(cid:258)(cid:202) konfiguracji us(cid:239)ugi przez jej u(cid:285)yciem. 239 Poleć książkęKup książkę AngularJS. Praktyczne przyk(cid:225)ady Zastosowanie us(cid:239)ugi typu provider mo(cid:285)e si(cid:218) wydawa(cid:202) nadmiernie skomplikowanym rozwi(cid:200)za- niem, gdy(cid:285) podobny efekt mo(cid:285)na by uzyska(cid:202), tworz(cid:200)c us(cid:239)ug(cid:218) typu constant, tak(cid:200) jak poni(cid:285)ej: angular.module( app ).constant( dbConfig , { database: mojaBaza , apiKey: mójKluczAPI }); A nast(cid:218)pnie wstrzykuj(cid:200)c j(cid:200) do istniej(cid:200)cej implementacji us(cid:239)ugi WorkoutService. Zastosowanie us(cid:239)ugi typu provider ma jednak t(cid:218) zalet(cid:218), (cid:285)e dane konfiguracyjne nie s(cid:200) dost(cid:218)p- ne globalnie. W przypadku u(cid:285)ycia us(cid:239)ugi typu constant, takiej jak dbConfig, ka(cid:285)da inna us(cid:239)uga lub kontroler mog(cid:239)yby uzyska(cid:202) dost(cid:218)p do nazwy bazy danych lub klucza API — wystarczy(cid:239)oby wstrzykn(cid:200)(cid:202) us(cid:239)ug(cid:218) dbConfig — a to by(cid:239)oby raczej niepo(cid:285)(cid:200)dane. Przedstawione do tej pory modyfikacje wci(cid:200)(cid:285) nie s(cid:200) jeszcze kompletne, o czym mo(cid:285)na si(cid:218) przekona(cid:202), od(cid:258)wie(cid:285)aj(cid:200)c stron(cid:218) z list(cid:200) treningów. W konsoli przegl(cid:200)darki zostanie wy(cid:258)wietlony komunikat unknown provider WorkoutServiceProvider1. Mamy tu do czynienia z b(cid:239)(cid:218)dem AngularJS zwi(cid:200)zanym z tym, (cid:285)e funkcja config modu(cid:239)u zo- sta(cid:239)a wywo(cid:239)ana przed zarejestrowaniem dostawcy. Przyczyn(cid:200) tego b(cid:239)(cid:218)du jest kolejno(cid:258)(cid:202) od- wo(cid:239)a(cid:241) do skryptów w pliku index.html, a konkretnie to, (cid:285)e odwo(cid:239)anie do skryptu app.js jest umieszczone przed odwo(cid:239)aniem do skryptu service.js. Powy(cid:285)szy b(cid:239)(cid:200)d zosta(cid:239) zg(cid:239)oszony (https://github.com/angular/angular.js/issues/7139) i opraco- wano metod(cid:218) jego omini(cid:218)cia — polega ona na wywo(cid:239)aniu funkcji config na samym ko(cid:241)cu, ju(cid:285) po zarejestrowaniu wszystkich dostawców i us(cid:239)ug. Wymaga to jednak przeniesienia kodu funkcji config do nowego pliku. Powy(cid:285)szy b(cid:239)(cid:200)d faktycznie wyst(cid:218)powa(cid:239) w czasie, kiedy pisa(cid:239)em ten rozdzia(cid:239), ale w nowszych wersjach AngularJS 1.3 problem ten zosta(cid:239) rozwi(cid:200)zany. Pomimo to wci(cid:200)(cid:285) b(cid:218)dziemy korzysta(cid:202) z przedstawionego poni(cid:285)ej rozwi(cid:200)zania, gdy(cid:285) zapewnia ono prawid(cid:239)owe dzia(cid:239)anie kodu niezale(cid:285)nie od u(cid:285)ywanej wersji AngularJS. Aby rozwi(cid:200)za(cid:202) opisany wcze(cid:258)niej problem, musimy skopiowa(cid:202) do roboczej wersji aplikacji pliki app.js i config.js dost(cid:218)pne w przyk(cid:239)adach do(cid:239)(cid:200)czonych do ksi(cid:200)(cid:285)ki, w katalogu rozdzial05\ punkt_kontrolny_1. Nast(cid:218)pnie trzeba zaktualizowa(cid:202) wywo(cid:239)anie funkcji configure us(cid:239)ugi Workout (cid:180)ServiceProvider w pliku config.js, podaj(cid:200)c w nim nazw(cid:218) bazy danych i klucz API. Nie mo(cid:285)emy tak(cid:285)e zapomnie(cid:202) o dodaniu odwo(cid:239)ania do pliku config.js na samym ko(cid:241)cu listy odwo(cid:239)a(cid:241) w pliku index.html. Je(cid:258)li teraz od(cid:258)wie(cid:285)ymy stron(cid:218) z list(cid:200) (cid:202)wicze(cid:241) lub treningów, przekonamy si(cid:218), (cid:285)e dane s(cid:200) pra- wid(cid:239)owo pobierane z serwera bazy danych. 1 Nieznany dostawca WorkoutServiceProvider — przyp. t(cid:239)um. 240 Poleć książkęKup książkę Rozdzia(cid:225) 5. • Dodawanie warstwy trwa(cid:225)o(cid:286)ci danych Je(cid:258)li masz problemy z tworzon(cid:200) implementacj(cid:200) aplikacji, to jej dzia(cid:239)aj(cid:200)c(cid:200) wersj(cid:218) znajdziesz w przyk(cid:239)adach do(cid:239)(cid:200)czonych do ksi(cid:200)(cid:285)ki, w katalogu rozdzial05\punkt_kontrolny_1. Przed prób(cid:200) uruchomienia tego kodu nale(cid:285)y tak(cid:285)e pami(cid:218)ta(cid:202), by zmieni(cid:202) nazw(cid:218) bazy danych i klucz API. Wszystko wygl(cid:200)da dobrze i lista jest wy(cid:258)wietlana prawid(cid:239)owo. No, prawie! Jest pewien drob- ny problem z list(cid:200) treningów. Je(cid:258)li dok(cid:239)adnie przyjrzymy si(cid:218) elementom tej listy (a w(cid:239)a(cid:258)ciwie jedynemu jej elementowi, przedstawionemu na rysunku 5.4), to zauwa(cid:285)ymy go bez trudu: Rysunek 5.4. Drobny b(cid:239)(cid:200)d na li(cid:258)cie treningów Okazuje si(cid:218), (cid:285)e po wprowadzeniu zmian przesta(cid:239)o dzia(cid:239)a(cid:202) wyliczanie czasu trwania treningu! Ale dlaczego tak si(cid:218) sta(cid:239)o? Aby odpowiedzie(cid:202) na to pytanie, musimy przeanalizowa(cid:202), w jaki sposób zosta(cid:239)y zaimplementowane te obliczenia. Us(cid:239)uga WorkoutService (w pliku model.js) defi- niuje funkcj(cid:218) totalWorkoutDuration, która s(cid:239)u(cid:285)y do wyliczania czasu trwania treningu. Ró(cid:285)nica polega na zawarto(cid:258)ci tablicy treningów dowi(cid:200)zanej do widoku. W poprzednich roz- dzia(cid:239)ach tworzyli(cid:258)my tablic(cid:218) z obiektami modelu, tworzonymi przy u(cid:285)yciu us(cid:239)ugi WorkoutPlan. Teraz natomiast dane s(cid:200) pobierane z serwera, do widoku dowi(cid:200)zywana jest zwyczajna tablica obiektów JavaScriptu, które z oczywistych powodów nie dysponuj(cid:200) (cid:285)adn(cid:200) logik(cid:200) do wykonywania oblicze(cid:241). Problem ten mo(cid:285)emy jednak rozwi(cid:200)za(cid:202) — wystarczy odwzorowa(cid:202) odpowied(cid:283) przes(cid:239)an(cid:200) z serwe- ra na obiekty klasy modelu i zwróci(cid:202) tablic(cid:218) tych obiektów. Odwzorowywanie danych z serwera na modele aplikacji Odwzorowywanie danych z serwera na model aplikacji i na odwrót nie jest konieczne, je(cid:258)li definicje modelu i posta(cid:202) danych przechowywanych na serwerze odpowiadaj(cid:200) sobie. Je(cid:258)li spojrzymy na klas(cid:218) modelu Exercise i na dane (cid:202)wicze(cid:241), które zapisali(cid:258)my w bazie MongoLab, oka(cid:285)e si(cid:218), (cid:285)e s(cid:200) identyczne, wi(cid:218)c (cid:285)adne odwzorowywanie nie jest konieczne. Odwzorowywanie odpowiedzi nades(cid:239)anej z serwera na dane modelu nabiera znaczenia gdy: (cid:81) model definiuje jakiekolwiek funkcje; (cid:81) dane modelu zapisane w bazie maj(cid:200) inn(cid:200) struktur(cid:218) ni(cid:285) ich reprezentacja u(cid:285)ywana w kodzie; 241 Poleć książkęKup książkę AngularJS. Praktyczne przyk(cid:225)ady (cid:81) ta sama klasa modelu jest u(cid:285)ywana do reprezentacji danych pochodz(cid:200)cych z ró(cid:285)nych (cid:283)róde(cid:239) (co mo(cid:285)e si(cid:218) zdarzy(cid:202) w aplikacjach typu mashup, (cid:239)(cid:200)cz(cid:200)cych dane pochodz(cid:200)ce z ró(cid:285)nych (cid:283)róde(cid:239)). Us(cid:239)uga WorkoutPlan jest doskona(cid:239)ym przyk(cid:239)adem znaczenia ró(cid:285)nic mi(cid:218)dzy reprezentacj(cid:200) mo- delu i jego trwale przechowywanymi danymi. Aby zauwa(cid:285)y(cid:202) te ró(cid:285)nice, wystarczy przyjrze(cid:202) si(cid:218) danym przedstawionym na rysunku 5.5. Rysunek 5.5. Posta(cid:202) danych modelu i danych przechowywanych na serwerze Oto dwie podstawowe ró(cid:285)nice mi(cid:218)dzy danymi modelu i danymi przechowywanymi na serwerze: (cid:81) Model definiuje funkcj(cid:218) totalWorkoutDuration. (cid:81) Inna jest reprezentacja tablicy exercises. W przypadku modelu tablica exercises zawiera obiekty Exercise (zapisane we w(cid:239)a(cid:258)ciwo(cid:258)ci details), natomiast w danych przechowywanych na serwerze znajduje si(cid:218) wy(cid:239)(cid:200)cznie identyfikator lub nazwa (cid:202)wiczenia. To wyra(cid:283)nie pokazuje, (cid:285)e wyczytywanie i zapisywanie treningów wymaga odwzorowywania modelu. Dla zachowania spójno(cid:258)ci mamy zamiar zaimplementowa(cid:202) odwzorowywanie danych, i to zarówno danych (cid:202)wicze(cid:241), jak i treningów. W pierwszej kolejno(cid:258)ci musimy zmieni(cid:202) implementacj(cid:218) funkcji getExercises us(cid:239)ugi Workout (cid:180)Service: service.getExercises = function () { return $http.get(collectionsUrl + /exercises , { params: { apiKey: apiKey } }) .then(function (response) { return response.data.map(function (exercise) { return new Exercise(exercise); }) }); }; A poniewa(cid:285) obecnie wynikiem zwracanym przez funkcj(cid:218) getExercises nie jest obiekt obietnicy zwracany przez us(cid:239)ug(cid:218) $http (wi(cid:218)cej o niej w dalszej cz(cid:218)(cid:258)ci tego podpunktu), lecz standardowy 242 Poleć książkęKup książkę Rozdzia(cid:225) 5. • Dodawanie warstwy trwa(cid:225)o(cid:286)ci danych obiekt obietnicy, to wsz(cid:218)dzie tam, gdzie wywo(cid:239)ujemy funkcj(cid:218) getExercises, zamiast funkcji success musimy u(cid:285)y(cid:202) funkcji then. Zmie(cid:241)my wi(cid:218)c w poni(cid:285)szy sposób implementacj(cid:218) funkcji init w kontrolerach ExercisesNav (cid:180)Controller i ExerciseListController: var init = function () { WorkoutService.getWorkouts().then(function (data) { $scope.workouts = data; }); }; Spójrzmy teraz na fragment kodu funkcji getExercises wyró(cid:285)niony pogrubieniem. Dzieje si(cid:218) w nim kilka interesuj(cid:200)cych rzeczy, które nale(cid:285)y zrozumie(cid:202): (cid:81) Po pierwsze, w funkcji zwrotnej przekazywanej w wywo(cid:239)aniu funkcji then (jako jej pierwszy parametr) wywo(cid:239)ujemy funkcj(cid:218) Array.map, która odwzorowuje tablic(cid:218) (cid:202)wicze(cid:241) zwrócon(cid:200) z serwera na tablic(cid:218) obiektów Exercise. Ogólnie rzecz bior(cid:200)c, funkcja Array.map jest zazwyczaj u(cid:285)ywana do odwzorowywania jednej tablicy na inn(cid:200). Wi(cid:218)cej informacji dotycz(cid:200)cych dzia(cid:239)ania tej funkcji mo(cid:285)na znale(cid:283)(cid:202) w dokumentacji Mozilla Developer Network (MDN), na stronie https://developer.mozilla.org/en-US/ docs/Web/JavaScript/Reference/Global_Objects/Array/map. (cid:81) Po drugie, ten kod stanowi doskona(cid:239)y przyk(cid:239)ad zastosowania (cid:239)a(cid:241)cuchów obietnic. Pierwsza obietnica jest zwracana przez wywo(cid:239)anie $http.get. Do niej do(cid:239)(cid:200)czamy funkcj(cid:218) zwrotn(cid:200) then, która tak(cid:285)e zwraca obietnic(cid:218), i to w(cid:239)a(cid:258)nie ten obiekt zostanie zwrócony do kodu wywo(cid:239)uj(cid:200)cego jako wynik. Ca(cid:239)y ten proces mo(cid:285)na zilustrowa(cid:202) za pomoc(cid:200) diagramu przedstawionego na rysunku 5.6. Rysunek 5.6. Schematyczna posta(cid:202) (cid:239)a(cid:241)cucha obietnic W przysz(cid:239)o(cid:258)ci, po wyznaczeniu pierwszej obietnicy ($http.get), zostanie wywo(cid:239)ana funkcja zwrotna then, do której zostanie przekazana lista (cid:202)wicze(cid:241) pobrana z serwera. Funkcja zwrotna then przetworzy odpowied(cid:283) i zwróci now(cid:200) tablic(cid:218) obiektów Exercise. Ta tablica zostanie nast(cid:218)pnie u(cid:285)yta podczas wyznaczania kolejnej obietnicy i przekazana do funkcji zwrotnej zdefiniowanej w kontrolerze ExerciseListController. 243 Poleć książkęKup książkę AngularJS. Praktyczne przyk(cid:225)ady Obietnica zwrócona przez funkcj(cid:218) then jest wyznaczana przez warto(cid:258)(cid:202) wynikow(cid:200) zwrócon(cid:200) przez jej funk- cj(cid:218) zwrotn(cid:200) success lub error. Dopiero funkcja zwrotna then zdefiniowana w kontrolerze ExerciseListController zapisuje przekazan(cid:200) tablic(cid:218) obiektów Exercise w zmiennej exercises. Na diagramie przedstawionym na rysunku 5.6 dane przekazywane w procesie wyznaczania poszczególnych obietnic zosta(cid:239)y przedstawione nad przerywanymi strza(cid:239)kami. (cid:146)a(cid:241)cuch obietnic dzia(cid:239)a jak potok do przetwarzania odpowiedzi; stanowi on wzorzec zapewniaj(cid:200)cy ogromne mo(cid:285)liwo(cid:258)ci i, jak pokaza(cid:239) powy(cid:285)szy przyk(cid:239)ad, mo(cid:285)na go u(cid:285)ywa(cid:202) do wykonywania naprawd(cid:218) interesuj(cid:200)cych rzeczy. (cid:81) Po trzecie, ze wzgl(cid:218)du na subteln(cid:200) ró(cid:285)nic(cid:218) mi(cid:218)dzy wynikiem zwracanym przez funkcje success i then, zamiast funkcji zwrotnej success obietnicy zwracanej przez wywo(cid:239)anie $http.get u(cid:285)ywamy funkcji then. Funkcja success zwraca pocz(cid:200)tkow(cid:200) obietnic(cid:218) (w naszym przypadku obietnica ta jest tworzona przez wywo(cid:239)anie $http.get), natomiast funkcja then zwraca now(cid:200) obietnic(cid:218), wyznaczan(cid:200) przez warto(cid:258)(cid:202) wynikow(cid:200) zwrócon(cid:200) przez funkcj(cid:218) success lub error, do których zosta(cid:239)a do(cid:239)(cid:200)czona funkcja then. Poniewa(cid:285) zamiast funkcji success u(cid:285)ywamy funkcji then, do funkcji zwrotnej jest przekazywany jeden obiekt zawieraj(cid:200)cy wszystkie cztery w(cid:239)a(cid:258)ciwo(cid:258)ci: config, data, header oraz status. Zanim zajmiemy si(cid:218) kolejnymi zagadnieniami, omówi(cid:218) dok(cid:239)adniej (cid:239)a(cid:241)cuchy obietnic, analizuj(cid:200)c kilka prostych przyk(cid:239)adów. To bardzo u(cid:285)yteczne rozwi(cid:200)zanie, zapewniaj(cid:200)ce ogromne mo(cid:285)liwo(cid:258)ci. Wyja(cid:258)nienie (cid:239)a(cid:241)cuchów obietnic Tworzenie (cid:239)a(cid:241)cuchów obietnic polega na przekazaniu wyniku wyznaczenia jednej obietnicy do innej obietnicy. Poniewa(cid:285) obietnica stanowi opakowanie dla operacji asynchronicznych, tworzenie (cid:239)a(cid:241)cuchów obietnic pozwala nam zarz(cid:200)dza(cid:202) kodem asynchronicznym poprzez zde- finiowanie sekwencji operacji, a nie w formie zagnie(cid:285)d(cid:285)onych wywo(cid:239)a(cid:241) zwrotnych. We wcze- (cid:258)niejszej cz(cid:218)(cid:258)ci rozdzia(cid:239)u spotka(cid:239)e(cid:258) si(cid:218) ju(cid:285) z przyk(cid:239)adem takiego (cid:239)a(cid:241)cucha obietnic — pos(cid:239)u(cid:285)y(cid:239) nam on do pobrania (cid:202)wicze(cid:241) z serwera (pierwsza operacja asynchroniczna), przekszta(cid:239)cenia ich (druga operacja asynchroniczna) oraz dowi(cid:200)zania do widoku (trzecia operacja asynchronicz- na). Proces ten zosta(cid:239) tak(cid:285)e przedstawiony na diagramie z rysunku 5.6. Technika ta umo(cid:285)liwia tworzenie (cid:239)a(cid:241)cuchów o dowolnej d(cid:239)ugo(cid:258)ci, o ile tylko wszystkie kolej- ne metody w (cid:239)a(cid:241)cuchu b(cid:218)d(cid:200) zwraca(cid:202) obietnice. W naszym przypadku obie metody, $http.get i then, zwracaj(cid:200) obietnice. Przeanalizujmy teraz znacznie prostszy przyk(cid:239)ad (cid:239)a(cid:241)cuchów obietnic. Kod tego przyk(cid:239)adu zo- sta(cid:239) przedstawiony poni(cid:285)ej: var promise = $q.when(1); var result = promise 244 Poleć książkęKup książkę Rozdzia(cid:225) 5. • Dodawanie warstwy trwa(cid:225)o(cid:286)ci danych .then(function (i) { return i + 1;}) .then(function (i) { return i + 1;}) .then(function (i) { return i + 1;}); .then(function (i) { console.log( Warto(cid:258)(cid:202) i wynosi: + i);}); Przyk(cid:239)ad demonstruj(cid:200)cy tworzenie (cid:239)a(cid:241)cucha obietnic jest dost(cid:218)pny w serwisie jsFiddle, na stronie http://jsfiddle.net/cmyworld/9ak1gahe/. Powy(cid:285)szy kod tworzy (cid:239)a(cid:241)cuch obietnic, przy czym ka(cid:285)da z funkcji w (cid:239)a(cid:241)cuchu inkrementuje przekazan(cid:200) do niej warto(cid:258)(cid:202) i przekazuje j(cid:200) dalej, do kolejnej obietnicy. Ostateczna warto(cid:258)(cid:202) i, przekazana do ostatniego wywo(cid:239)ania funkcji then, b(cid:218)dzie wynosi(cid:239)a 4. Funkcja $q.when(1) zwraca obietnic(cid:218), której wyznaczenie zwróci warto(cid:258)(cid:202) 1. Zgodnie z podanymi wcze(cid:258)niej informacjami tworzenie (cid:239)a(cid:241)cuchów obietnic jest mo(cid:285)liwe dlatego, (cid:285)e funkcja then zwraca obietnic(cid:218). W efekcie wyznaczania obietnicy zwracana jest warto(cid:258)(cid:202) funkcji zwrotnej success lub error. Je(cid:258)li przyjrzymy si(cid:218) poprzedniemu przyk(cid:239)adowi, to za- uwa(cid:285)ymy, (cid:285)e w ka(cid:285)dej funkcji zwrotnej (z wyj(cid:200)tkiem ostatniej), wykonywanej w przypadku prawid(cid:239)owego wyznaczenia obietnicy, zosta(cid:239)a u(cid:285)yta instrukcja return. Nieco zaskakuj(cid:200)ce mo(cid:285)e by(cid:202) natomiast dzia(cid:239)anie (cid:239)a(cid:241)cucha obietnic w przypadku, gdy ich wy- znaczenie zako(cid:241)czy si(cid:218) niepowodzeniem. Najlepiej b(cid:218)dzie zilustrowa(cid:202) go na przyk(cid:239)adzie: var errorPromise = $q.reject( niepowodzenie ); var resultError = errorPromise.then(function (data) { return powodzenie ; }, function (e) { return niepowodzenie ; }); resultError.then(function (data) { console.log( W funkcji zwrotnej success, dane: + data); }, function (e) { console.log( W funkcji zwrotnej error, dane: + e); }); Wywo(cid:239)anie $q.reject tworzy obietnic(cid:218), która zostanie odrzucona i zwróci przy tym warto(cid:258)(cid:202) error. A zatem tak(cid:285)e wyznaczenie obietnicy resultError zwróci warto(cid:258)(cid:202) error. Teraz jednak powstaje pytanie: jaki komunikat wy(cid:258)wietli funkcja zwrotna resultError.then? Okazuje si(cid:218), (cid:285)e komunikatem tym b(cid:218)dzie: W funkcji zwrotnej success, dane: niepowodzenie, gdy(cid:285) zostanie wywo(cid:239)ana funkcja zwrotna success, a nie error. A to z kolei wynika z faktu, (cid:285)e w obu funkcjach zwrotnych — success i error — przekazanych w wywo(cid:239)aniu errorPromise.then (lub resultError) u(cid:285)yli(cid:258)my zwyczajnej instrukcji return. 245 Poleć książkęKup książkę AngularJS. Praktyczne przyk(cid:225)ady Gdyby(cid:258)my chcieli, by wyznaczanie wszystkich obietnic w (cid:239)a(cid:241)cuchu zako(cid:241)czy(cid:239)o si(cid:218) niepowo- dzeniem, to w ka(cid:285)dej funkcji zwrotnej error musieliby(cid:258)my odrzuci(cid:202) obietnic(cid:218). Zmie(cid:241)my zatem obietnic(cid:218) resultError w nast(cid:218)puj(cid:200)cy sposób: var resultError = errorPromise.then(function (data) { return powodzenie ; }, function (e) { return $q.reject(e); }); W tym przypadku w nast(cid:218)pnym wywo(cid:239)aniu then w (cid:239)a(cid:241)cuchu zostanie wywo(cid:239)ana prawid(cid:239)owa funkcja zwrotna, a w oknie konsoli pojawi si(cid:218) komunikat: W funkcji zwrotnej error, dane: niepowodzenie. Zwrócenie w funkcji zwrotnej error wyniku wywo(cid:239)ania $q.reject(e) sprawi, (cid:285)e wyznaczon(cid:200) warto(cid:258)ci(cid:200) obietnicy resultError b(cid:218)dzie odrzucona obietnica (wywo(cid:239)anie $q.reject zwraca obietnic(cid:218), która zawsze b(cid:218)dzie odrzucona). Tworzenie (cid:239)a(cid:241)cuchów obietnic jest rozwi(cid:200)zaniem zapewniaj(cid:200)cym ogromne mo(cid:285)liwo(cid:258)ci, a jego dobre opanowanie pozwoli Ci tworzy(cid:202) bardziej zwi(cid:218)z(cid:239)y i lepiej zorganizowany kod. W tym rozdziale b(cid:218)dziemy go u(cid:285)ywali bardzo intensywnie, do obs(cid:239)ugi odpowiedzi przesy(cid:239)anych z ser- wera oraz przetwarzania i wczytywania danych. A teraz wró(cid:202)my do prac nad rozwojem aplikacji, do miejsca, w którym je wcze(cid:258)niej przerwali(cid:258)my, czyli do wczytywania z serwera danych (cid:202)wicze(cid:241) i treningów. Wczytywanie danych (cid:202)wicze(cid:241) i treningów z serwera Skoro poprawili(cid:258)my ju(cid:285) implementacj(cid:218) funkcji getExercise us(cid:239)ugi WorkoutService, mo(cid:285)emy zaimplementowa(cid:202) tak(cid:285)e inne operacje zwi(cid:200)zane z pobieraniem danych (cid:202)wicze(cid:241) i treningów. W tym celu nale(cid:285)y skopiowa(cid:202) implementacje funkcji getExercise, getWorkouts oraz getWorkout us(cid:239)ugi WorkoutService z pliku services.js umieszczonego w katalogu rozdzial05\punkt_kontrolny_2\ app\js\shared. Funkcje getWorkout i getExercise pobieraj(cid:200) odpowiednie dane na podstawie nazwy treningu lub (cid:202)wiczenia. Ka(cid:285)dy element baz danych MongoLab ma w(cid:239)a(cid:258)ciwo(cid:258)(cid:202) _id, która w unikalny sposób go identyfi- kuje. W przypadku obiektów Exercise i WorkoutPlan tym unikalnym identyfikatorem jest nazwa (cid:202)wiczenia b(cid:200)d(cid:283) treningu, dlatego nazwa i w(cid:239)a(cid:258)ciwo(cid:258)(cid:202) _id zawsze b(cid:218)d(cid:200) identyczne. Nale(cid:285)y zwróci(cid:202) szczeg
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

AngularJS. Praktyczne przykłady
Autor:
,

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: