TL; DR
1) Gdy używasz fabryki , tworzysz obiekt, dodajesz do niego właściwości, a następnie zwraca ten sam obiekt. Po przekazaniu tej fabryki do kontrolera właściwości tego obiektu będą teraz dostępne w tym kontrolerze za pośrednictwem fabryki.
app.controller('myFactoryCtrl', function($scope, myFactory){
$scope.artist = myFactory.getArtist();
});
app.factory('myFactory', function(){
var _artist = 'Shakira';
var service = {};
service.getArtist = function(){
return _artist;
}
return service;
});
2) Gdy używasz usługi , Angular tworzy ją za kulisami ze słowem kluczowym „new”. Z tego powodu dodasz właściwości do „tego”, a usługa zwróci „to”. Po przekazaniu usługi do kontrolera właściwości „this” będą teraz dostępne na tym kontrolerze za pośrednictwem usługi.
app.controller('myServiceCtrl', function($scope, myService){
$scope.artist = myService.getArtist();
});
app.service('myService', function(){
var _artist = 'Nelly';
this.getArtist = function(){
return _artist;
}
});
Non TL; DR
1)
Fabryki to najpopularniejszy sposób tworzenia i konfigurowania usługi. Naprawdę niewiele więcej niż mówi TL; DR. Wystarczy utworzyć obiekt, dodać do niego właściwości, a następnie zwrócić ten sam obiekt. Następnie, po przekazaniu fabryki do kontrolera, te właściwości obiektu będą teraz dostępne w tym kontrolerze przez fabrykę. Bardziej obszerny przykład znajduje się poniżej.
app.factory('myFactory', function(){
var service = {};
return service;
});
Teraz wszelkie właściwości, które dołączamy do „usługi”, będą dostępne, gdy przekażemy „myFactory” do naszego kontrolera.
Dodajmy teraz trochę „prywatnych” zmiennych do naszej funkcji zwrotnej. Nie będą one bezpośrednio dostępne z poziomu kontrolera, ale w końcu skonfigurujemy metody getter / setter dla „service”, aby móc zmienić te „prywatne” zmienne w razie potrzeby.
app.factory('myFactory', function($http, $q){
var service = {};
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK';
return _finalUrl
}
return service;
});
Tutaj zauważysz, że nie przypisujemy tych zmiennych / funkcji do „usługi”. Po prostu tworzymy je w celu późniejszego wykorzystania lub modyfikacji.
- baseUrl to podstawowy adres URL wymagany przez interfejs API iTunes
- _artist to artysta, którego chcemy szukać
- _finalUrl to końcowy iw pełni zbudowany adres URL, do którego zadzwonimy do iTunes makeUrl to funkcja, która utworzy i zwróci nasz przyjazny adres URL dla iTunes.
Teraz, gdy nasze zmienne pomocnicze / prywatne i funkcja są już na miejscu, dodajmy pewne właściwości do obiektu „service”. Cokolwiek zastosujemy w „usłudze”, będziemy mogli bezpośrednio używać w dowolnym kontrolerze, w którym przekazujemy „myFactory”.
Stworzymy metody setArtist i getArtist, które po prostu zwrócą lub ustawią artystę. Stworzymy również metodę, która wywoła interfejs API iTunes z naszym utworzonym adresem URL. Ta metoda zwróci obietnicę, która spełni się, gdy dane wrócą z interfejsu API iTunes. Jeśli nie miałeś dużego doświadczenia w korzystaniu z obietnic w Angular, bardzo polecam głębokie zanurzenie się w nich.
Poniżej setArtist akceptuje wykonawcę i umożliwia ustawienie wykonawcy. getArtist zwraca artystę callItunes najpierw wywołuje makeUrl () w celu zbudowania adresu URL, którego będziemy używać z naszym żądaniem $ http. Następnie ustawia obiekt obietnicy, wysyła żądanie $ http z naszym ostatnim adresem URL, a ponieważ $ http zwraca obietnicę, jesteśmy w stanie wywołać .success lub .error po naszej prośbie. Następnie wypełniamy naszą obietnicę za pomocą danych iTunes lub odrzucamy ją komunikatem „Wystąpił błąd”.
app.factory('myFactory', function($http, $q){
var service = {};
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
service.setArtist = function(artist){
_artist = artist;
}
service.getArtist = function(){
return _artist;
}
service.callItunes = function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
}
return service;
});
Teraz nasza fabryka jest kompletna. Jesteśmy teraz w stanie wstrzyknąć „myFactory” do dowolnego kontrolera, a następnie będziemy mogli wywoływać nasze metody, które podłączyliśmy do naszego obiektu usługi (setArtist, getArtist i callItunes).
app.controller('myFactoryCtrl', function($scope, myFactory){
$scope.data = {};
$scope.updateArtist = function(){
myFactory.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myFactory.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
});
W powyższym kontrolerze wprowadzamy usługę „myFactory”. Następnie ustawiamy właściwości naszego obiektu $ scope, które pochodzą z danych z „myFactory”. Jedynym trudnym kodem powyżej jest to, że nigdy wcześniej nie dotykałeś obietnic. Ponieważ callItunes zwraca obietnicę, jesteśmy w stanie użyć metody .then () i ustawić wartość $ scope.data.artistData tylko wtedy, gdy nasza obietnica zostanie wypełniona danymi iTunes. Zauważysz, że nasz kontroler jest bardzo „cienki”. Wszystkie nasze logiczne i trwałe dane znajdują się w naszym serwisie, a nie w naszym kontrolerze.
2) Usługa
Być może największą rzeczą, o której należy wiedzieć podczas tworzenia Usługi, jest to, że jest ona tworzona za pomocą słowa kluczowego „new”. Dla ciebie guru JavaScript powinien dać ci dużą wskazówkę dotyczącą natury kodu. Dla tych z ograniczonym doświadczeniem w JavaScript lub dla tych, którzy nie są zbyt dobrze zaznajomieni z tym, co faktycznie robi „nowe” słowo kluczowe, przejrzyjmy niektóre podstawy JavaScript, które ostatecznie pomogą nam zrozumieć naturę Usługi.
Aby naprawdę zobaczyć zmiany, które następują po wywołaniu funkcji słowem kluczowym „new”, utwórzmy funkcję i wywołaj ją słowem kluczowym „new”, a następnie pokażmy, co robi tłumacz, gdy zobaczy słowo kluczowe „new”. Oba wyniki końcowe będą takie same.
Najpierw stwórzmy naszego Konstruktora.
var Person = function(name, age){
this.name = name;
this.age = age;
}
Jest to typowa funkcja konstruktora JavaScript. Teraz za każdym razem, gdy wywołujemy funkcję Osoba za pomocą słowa kluczowego „new”, „to” zostanie powiązane z nowo utworzonym obiektem.
Dodajmy teraz metodę do prototypu naszej Osoby, aby była dostępna w każdej instancji naszej „klasy” Osoby.
Person.prototype.sayName = function(){
alert('My name is ' + this.name);
}
Teraz, ponieważ umieszczamy funkcję sayName na prototypie, każda instancja Person będzie mogła wywołać funkcję sayName, aby zaalarmować nazwę tej instancji.
Teraz, gdy mamy prototyp konstruktora Person i funkcję sayName na jego prototypie, utwórzmy instancję Person, a następnie wywołaj funkcję sayName.
var tyler = new Person('Tyler', 23);
tyler.sayName(); //alerts 'My name is Tyler'
Cały kod do tworzenia konstruktora Person, dodawania funkcji do jego prototypu, tworzenia instancji Person, a następnie wywoływania funkcji na prototypie wygląda tak.
var Person = function(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayName = function(){
alert('My name is ' + this.name);
}
var tyler = new Person('Tyler', 23);
tyler.sayName(); //alerts 'My name is Tyler'
Teraz spójrzmy na to, co się właściwie dzieje, gdy używasz słowa kluczowego „new” w JavaScript. Pierwszą rzeczą, którą powinieneś zauważyć, jest to, że po użyciu „new” w naszym przykładzie jesteśmy w stanie wywołać metodę (sayName) na „tyler” tak, jakby to był obiekt - to dlatego, że tak jest. Po pierwsze wiemy, że nasz konstruktor Person zwraca obiekt, bez względu na to, czy widzimy to w kodzie, czy nie. Po drugie, wiemy, że ponieważ nasza funkcja sayName znajduje się na prototypie, a nie bezpośrednio na instancji Person, obiekt, który zwraca funkcja Person, musi delegować do swojego prototypu podczas nieudanych wyszukiwań. Mówiąc prościej, kiedy wywołujemy tyler.sayName () interpreter mówi „OK, przejrzę właśnie utworzony obiekt„ tyler ”, zlokalizuj funkcję sayName, a następnie wywołaj ją. Chwileczkę, nie widzę tego tutaj - widzę tylko imię i wiek, pozwól mi sprawdzić prototyp. Tak, wygląda na to, że jest na prototypie, nazwijmy to ”.
Poniżej znajduje się kod wyjaśniający, co tak naprawdę robi „nowe” słowo kluczowe w JavaScript. Jest to w zasadzie przykład kodu powyższego akapitu. Umieściłem „widok tłumacza” lub sposób, w jaki tłumacz widzi kod w notatkach.
var Person = function(name, age){
//The line below this creates an obj object that will delegate to the person's prototype on failed lookups.
//var obj = Object.create(Person.prototype);
//The line directly below this sets 'this' to the newly created object
//this = obj;
this.name = name;
this.age = age;
//return this;
}
Mając już wiedzę o tym, co tak naprawdę robi „nowe” słowo kluczowe w JavaScript, tworzenie Usługi w Angular powinno być łatwiejsze do zrozumienia.
Najważniejszą rzeczą do zrozumienia podczas tworzenia Usługi jest świadomość, że Usługi są tworzone za pomocą słowa kluczowego „new”. Łącząc tę wiedzę z naszymi powyższymi przykładami, powinieneś teraz wiedzieć, że będziesz przypisywać swoje właściwości i metody bezpośrednio do „tego”, który następnie zostanie zwrócony z samej Usługi. Spójrzmy na to w akcji.
W przeciwieństwie do tego, co pierwotnie zrobiliśmy z przykładem Factory, nie musimy tworzyć obiektu, a następnie zwracać go, ponieważ, jak wspomniano wiele razy wcześniej, użyliśmy słowa kluczowego „new”, aby interpreter utworzył ten obiekt, zlecając mu to prototyp, a następnie zwróć go nam bez konieczności wykonywania pracy.
Po pierwsze, stwórzmy naszą funkcję „prywatną” i pomocniczą. Powinno to wyglądać bardzo znajomo, ponieważ zrobiliśmy dokładnie to samo z naszą fabryką. Nie wyjaśnię, co robi tutaj każda linia, ponieważ zrobiłem to w przykładzie fabrycznym. Jeśli jesteś zdezorientowany, przeczytaj ponownie przykład fabryczny.
app.service('myService', function($http, $q){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
});
Teraz dołączymy wszystkie nasze metody, które będą dostępne w naszym kontrolerze do „tego”.
app.service('myService', function($http, $q){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
this.setArtist = function(artist){
_artist = artist;
}
this.getArtist = function(){
return _artist;
}
this.callItunes = function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
}
});
Teraz, podobnie jak w naszej fabryce, setArtist, getArtist i callItunes będą dostępne w dowolnym kontrolerze, do którego przekazujemy myService. Oto kontroler myService (który jest prawie dokładnie taki sam jak nasz kontroler fabryczny).
app.controller('myServiceCtrl', function($scope, myService){
$scope.data = {};
$scope.updateArtist = function(){
myService.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myService.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
});
Jak wspomniałem wcześniej, kiedy naprawdę zrozumiesz, co robi „nowość”, usługi są prawie identyczne z fabrykami w Angular.