2014-09-30 13 views
7

Mam problem z zawijaniem głowy wokół obietnic. Korzystam z interfejsu Google Earth API, aby wykonać "trasę" adresów. Wycieczka to tylko animacja, która trwa około minuty, a po jej zakończeniu kolejna powinna wystartować.AngularJS: łupiąc obietnice ponad dla każdej pętli

Oto moja funkcja, która robi objazd:

var tourAddress = function (address) { 
     return tourService.getLatLong(address).then(function (coords) { 
      return tourService.getKmlForCoords(coords).then(function (kml) { 
       _ge.getTourPlayer().setTour(kml); 
       _ge.getTourPlayer().play(); 

       var counter = 0; 
       var d = $q.defer(); 
       var waitForTour = function() { 
        if (counter < _ge.getTourPlayer().getDuration()) { 
         ++counter; 
         setTimeout(waitForTour, 1000); 
        } else { 
         d.resolve(); 
        } 
       }; 

       waitForTour(); 

       return d.promise; 
      }); 
     }); 
    } 

Wydaje się to całkiem dobrze działa. Rozpoczyna animację i zwraca obietnicę, która zostanie rozwiązana po zakończeniu animacji. Teraz mam tablicę adresów, i chcę zrobić foreach turystycznej z nich:

$scope.addresses.forEach(function (item) { 
     tourAddress(item.address).then(function(){ 
      $log.log(item.address + " complete"); 
     }); 
}); 

Kiedy to zrobić, wszyscy oni wykonywać w tym samym czasie (Google Earth robi animację na ostatni adres) i wszystkie kończą się w tym samym czasie. Jak połączyć te ogniwa w ogień po zakończeniu poprzedniego?

UPDATE

użyłem @ phtrivier za wielką pomoc, aby go osiągnąć:

$scope.addresses.reduce(function (curr,next) { 
     return curr.then(function(){ 
      return tourAddress(next.address) 
     }); 
    }, Promise.resolve()).then(function(){ 
     $log.log('all complete'); 
    }); 

Odpowiedz

5

Masz rację, wnioski są wykonywane natychmiast, ponieważ wywołanie tourAddress (item.address) Czy zażądania i zwraca Promise rozwiązany, gdy żądanie jest wykonywana.

Ponieważ wywołujesz tourAddress w pętli, generowanych jest wiele Promises, ale nie zależą one od siebie nawzajem.

To, czego chcesz, to zadzwonić do biuraAdres, wziąć zwróconą obietnicę, zaczekać na jej rozwiązanie, a następnie ponownie zadzwonić na adres tourAddress z innym adresem i tak dalej.

ręcznie, trzeba by napisać coś takiego:

tourAddress(addresses[0]) 
    .then(function() { 
    return tourAddress(addresses[1]); 
    }) 
    .then(function() { 
    return tourAddress(addresses[2]); 
    }) 
    ... etc... 

Jeśli chcesz to zrobić automatycznie (nie jesteś pierwszy z nich: How can I execute array of promises in sequential order?), można spróbować zmniejszyć listę adresu do pojedyncza obietnica, która wykona cały łańcuch.

_.reduce(addresses, function (memo, address) { 

    return memo.then(function (address) { 
     // This returns a Promise 
     return tourAddress(address); 
    }); 

}, Promise.resolve()); 

(to jest pseudo-kod, który wykorzystuje podkreślenia i Bluebird, ale powinno być elastyczne)

+1

ahh Dziękuje, myślę, że 'reduce' jest to, czego szukam. Zobaczę, czy mogę to zrobić działa – Jonesopolis

+1

mam to, jeszcze raz dziękuję za poradę – Jonesopolis

+2

Dlaczego '_.reduce'? Równie łatwo można było zrobić 'adresy.reduce' –

Powiązane problemy