AngularJS $ http czekaj odpowiedź


Jestem nowy w javascript/angularjs.Chcę pokazać wyskakujące okienko bootstrap po najechaniu myszą na niektóre elementy.
Stworzyłem w tym celu dyrektywę
(function(angular, app) {
app.directive('popOver',["$window","$http",function($window,$http){
return function(scope,elem,attrs){
elem.on('mouseover',function(){
console.log('mouseover');
var data = scope.$apply(attrs.popOver);
console.log('in directive again');
console.log(data);
});
};
}]);
})(angular, app);

wartość dyrektywy jest funkcją
<span class="asdf" pop-over="getVCard(id)">name</span>
Funkcja vcard (id) jest zdefiniowana w moim kontrolerze angularjs. Sprawdza, czy dane są już w magazynie lokalnym, a jeśli tak, zwraca dane. w przeciwnym razie wysyła żądanie pobrania $ http i przechowuje dane w localstorage.
$scope.getVCard = function(id){ var vcardKey = vcardKeyPrefix+id; var vCardFromLS = localStorageService.get(vCardKey);
if(vCardFromLS){
return localStorageService.get(vCardKey);
} $http.get(app.common.vcardUrl(id)).
success(function(data){
localStorageService.set(vCardKey,data);
}).
error(function(error){
F1.common.error(data,function(){});
}); return localStorageService.get(vCardKey);
};

Ponieważ $ http zwraca obietnicę, moja dyrektywa jest niezdefiniowana. Jak mogę się upewnić, że funkcja
getVCard
zwraca synchronicznie?
Przeczytałem szereg wyników po googlowaniu. Ale sugerowanym pomysłem jest użycie wywołań zwrotnych. Ale nie jestem pewien, jak wywołania zwrotne sprawią, że będzie to synchroniczne. Każda pomoc byłaby bardzo mile widziana.

UPDATE 1

(w odpowiedzi na komentarz Foo L)
Planowałem używać tej samej dyrektywy w wielu miejscach. wyskakujące okienka z wizytówkami vCard, informacjami o produktach i tak dalej. Jedyną różnicą będzie argument dotyczący dyrektywy pop-over. Dlatego dyrektywa będzie martwić się tylko wyświetlaniem wyskakującego okienka. Skąd wziąć dane będzie osobna funkcja, która jest przekazywana do dyrektywy
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Nie możesz wymusić synchronizacji
$ http.get ()
. Ponieważ
$ http.get ()
jest nieuniknione

asynchronicznie
, możesz zwrócić tylko obietnicę wartości, a nie samą wartość.
A ponieważ musisz to zrobić, wywołując
$ http.get ()
, musisz również zwrócić obietnicę w innym stanie - gdy
vCardFromLS
pomyślnie pobierze z magazynu lokalnego. Gwarantuje to, że obiekt zwracany przez dowolne wywołanie funkcji
$ scope.getVCard ()
ma metodę
.then ()
, to znaczy tę obietnicę, niezależnie od tego, czy
$ http.get ()
lub nie.
Więc kod powinien wyglądać mniej więcej tak:
$scope.getVCard = function(id) {
var vcardKey = vcardKeyPrefix + id;
var vCardFromLS = localStorageService.get(vCardKey);
var dfrd = $q.defer();
if(vCardFromLS) {
dfrd.resolve(localStorageService.get(vCardKey));
}
else {
$http.get(app.common.vcardUrl(id)).success(function(data) {
localStorageService.add(vCardKey, data);//.add() rather than .set() ?
dfrd.resolve(data);
}).error(function(error) {
F1.common.error(data, function() {
dfrd.reject('$http.get(app.common.vcardUrl(id)) failed');
});
});
}
return dfrd.promise;
};

Teraz musisz się upewnić, że odpowiedź na
$ scope.getVCard ()
jest odpowiednio obsłużona, na przykład:
$scope.getVCard(id).then(function(data) {
//success - do whatever is required with data
}, function(reason) {
//failure - log and/or display `reason` as an error message
})


EDIT

:
Mój "... ty też

powinien

zwrócić obietnicę pod innym warunkiem… ”to przesada.
Powinienem był powiedzieć „… ty

czy możesz

aby uprościć sprawę, zwróć obietnicę pod innym warunkiem… ”.
Inną możliwością jest rozgałęzienie w zależności od tego, czy zwrócono obietnicę, czy inny typ obiektu/wartości. Jest to jednak kłopotliwe i zwykle powoduje powielanie kodu.

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się