2014-07-17 13 views
20

Staram się zrozumieć obietnice w JavaScript (w szczególności AngularJS).Natychmiast zwróć rozstrzygniętą obietnicę za pomocą AngularJS

Mam funkcję w usłudze, nazwijmy ją fooService, która sprawdza, czy załadowaliśmy jakieś dane. Jeśli tak, po prostu chcę go do powrotu, a jeśli nie mamy, musimy załadować dane i powrócić obietnicę:

this.update = function(data_loaded) { 
    if (data_loaded) return; // We've loaded the data, no need to update 

    var promise = Restangular.all('someBase').customGet('foo/bar').then(function(data) { 
     // Do something with the data here 
    } 

    return promise; 
} 

mam inną funkcję, która następnie wywołuje funkcję update o fooService jak tak :

fooService.update(data_loaded).then(function() { 
    // Do something here when update is finished 
}) 

Mój problem jest to, że jeśli nie trzeba ładować dane w funkcji update, obietnica nie zostanie zwrócony, więc .then() nie nazywa w moim innej funkcji. Jakie powinno być podejście? W zasadzie chcę zwrócić rozstrzygniętą obietnicę natychmiast z funkcji update(), jeśli nie musimy pobierać danych z połączenia Restangular?

Odpowiedz

26

Obecna odpowiedź akceptowana jest nadmiernie skomplikowane i nadużywa deferred anti pattern. Oto prostsze podejście:

this.update = function(data_loaded) { 
    if (data_loaded) return $q.when(data); // We've loaded the data, no need to update 

    return Restangular.all('someBase').customGet('foo/bar') 
          .then(function(data) { 
     // Do something with the data here 
    }); 
}; 

Albo jeszcze dalej:

this._updatep = null; 
this.update = function(data_loaded) { // cached 
    this._updatep = this._updatep || Restangular.all('someBase') // process in 
               .customGet('foo/bar'); //.then(.. 
    return this._updatep; 
}; 
+1

Dzięki za napiwek. Zawsze brakowało mi składni "Q (initialVal)" [Kris Kowal's Q] (https://github.com/kriskowal/q) i powinienem znać '$ q.when (dane)' może zrobić tę samą sztuczkę. – runTarm

-1

Można użyć $q.defer() takiego:

this.update = function (data_loaded) { 
    var deferred = $q.defer(); 

    if (data_loaded) { 
     deferred.resolve(null); // put something that your callback will know the data is loaded or just put your loaded data here. 
    } else { 
     Restangular.all('someBase').customGet('foo/bar').then(function(data) { 
      // Do something here when update is finished 
      deferred.resolve(data); 
     } 
    } 

    return deferred.promise; 
}; 

nadzieję, że to pomaga.

+0

Dokładnie tego, czego szukałem - dzięki! :) – samturner

+8

Nie mam pojęcia, jak to zostało dwukrotnie wznowione, jest to odroczony wzór anty i można go znacznie uprościć. –

+0

Nie jest to tylko odroczona antipattern, ale także nie propaguje błędów. – Bergi

6

Serwis AngularJS $q pomoże Ci tutaj. Jest to bardzo podobna biblioteka obietnicy Kris Kowal's Q.

Gdy masz metodę asynchroniczną, która może zwrócić obietnicę lub wartość, użyj metody $q.when. Potrwa to, co kiedykolwiek zostanie mu przekazane, czy to jest obietnica, czy wartość i utworzy obietnicę, która zostanie rozwiązana/odrzucona na podstawie przekazanej obietnicy lub rozwiązana, jeśli wartość zostanie przekazana.

$q.when(fooService.update(data_loaded)).then(function(data){ 
    //data will either be the data returned or the data 
    //passed through from the promise 
}) 

a następnie w funkcji aktualizacji przywrócić dane, zamiast po prostu powrocie

if (data_loaded) return data_loaded; 
31

Jak twoja obietnica użyć tej samej składni jak JavaScript rodzimej jeden, można użyć i zwracają już rozwiązany obietnicę JavaScript: Promise.resolve()

return(Promise.resolve("MyReturnValue")); 
+0

Oto odpowiedź, której pragnąłem; Mam wartość; jest gotowy, po prostu chcę go zawrzeć w obietnicy, aby spełnić API, które oczekują Obietnicy ... Tak więc, podczas gdy PO chciał zapytać: "Natychmiast zwróć ustaloną obietnicę", ** chciałem "zwrócić Obietnicę, która Postanowiłem od razu (dosłownie) " –

+0

Tego też chciałem. Mam obiekt i po prostu muszę zwrócić obietnicę, ponieważ tego oczekuje API. – richard

+0

Uważaj na obsługę IE w tej odpowiedzi. $ q zapewnia obsługę wielu przeglądarek –