piątek, 29 sierpnia 2014

AngularJs - module.service w poszukiwaniu znaczenia i ... operatora new

Witam,

Trochę czasu minęło od ostatniego postu, ale tak się złożyło, że ostatnio miałem naprawdę sporo pracy... Ale dobra, ostatnio poznaję angulara i dzisiaj zastanawiałem się po raz kolejny jaka jest różnica pomiędzy usługą (module.service) a fabryką (module.factory), owszem czytałem na ten temat i najczęściej spotykałem się z wyjaśnieniem, że w przypadku usługi
przekazana funkcja jest konstruktorem z którego przy pomocy operatora new zwrócona zostanie instancja nowego obiektu.

Dla potwierdzenia poniżej przytaczam opis ze styleguida autorstwa Todd Motto( https://github.com/toddmotto/angularjs-styleguide ), który to swoja drogą jest wdrażany w naszej firmie.

All Angular Services are singletons, using .service() or .factory() differs the way Objects are created.

Services: act as a constructor function and are instantiated with the new keyword. Use this for public methods and variables

Factory: Business logic or provider modules, return an Object or closure

Always return a host Object instead of the revealing Module pattern due to the way Object references are bound and updated

Ale dzisiaj przeglądałem kod napisany przez kolegę i tam jego funkcja przekazana do module.service nie wyglądała jak konstruktor, tylko raczej jak funkcja którą można zobaczyć w fabryce.


Oczywiście powyższy kod działa, aczkolwiek funkcja przekazana jako argument do funckji module.service nie jest konstruktorem tylko sama zwraca obiekt jak w fabryce.

Zajrzałem zatem do kodu angulara w poszukiwaniu tego operatora `new`, którego to przytaczają wszędzie. Poniżej widać deklarację funkcji service.


Widać, że usługa jest fabryką zwracającą instancję obiektu utworzoną przez $injectora.istantiate przy użyciu funkcji przekazanej w parametrze constructor. Póki co nie widać operatora new.

Zaglądam zatem do funkcji instantiate obiektu $injector.


Faktycznie jest operator new (w linii 8), tylko zaraz... jest on wykorzystany do utworzenia pustego obiektu i przypisania go do zmiennej instance, a dalej nie widać innego operatora new zatem jak ten obiekt powstał...? A jest jeszcze funkcja invoke, ok sprawdźmy ją (pominąłem w niej fragment operujący na przekazanych argumentach)
Do funkcji invoke przekazywane są trzy parametry: pierwszy w naszym przypadku to funkcja przekazana do metody service, druga natomiast to utworzony pusty obiekt w metodzie instatiate   


Nie ma tu również operatora new, ale jest fajny kawałek kodu  fn.apply(self, args), który powoduje zwrócenie naszego obiektu jeżeli funkcja fn nie jest konstruktorem, natomiast jeżeli funkcja fn jest konstruktorem to z meotdy invoke zostanie zwrócony undefined ?! i nowy obiekt dostępny w zmiennej instance w funkcji instantiate.

Dzisiejsze spostrzeżenia utrwaliły mnie w poczuciu braku zrozumienia różnicy miedzy service a factory oraz jakie jest ich przeznaczenie, dlatego, żeby uniknąć nieporozumień zostaję przy stylu który opisał Todd Motto.
Poznałem również - przynajmniej dla mnie nowy - sposób  na  utworzenie nowego obiektu  przy użyciu dowolnego konstruktora z wykorzystaniem metody .apply(),
dzięki czemu można stworzyć sobie proxy do tworzenia obiektu (to zachowanie fajnie opisuje Ben Nadel w swoim blogu http://www.bennadel.com/blog/2291-invoking-a-native-javascript-constructor-using-call-or-apply.htm).

Warto zajrzeć do kodu źródłowego bo można się zawsze trochę nauczyć :-).
  
  

1 komentarz:

  1. Needed to compose you a very little word to thank you yet again regarding the nice suggestions you’ve contributed here AngularJS Online Course India

    OdpowiedzUsuń