2016-03-08 12 views
11

Próbuję zrozumieć obietnicę API i łańcuchów, w szczególności czas, kiedy $timeout jest używany z .then(). To, czego się spodziewałem, to to, że ponieważ $timeout zwróci obietnicę, .then() nie zostanie wywołane, dopóki nie zostanie rozwiązane.

Ale zamiast ABAB, to ABBA cały czas.

Jak mogę skorzystać z interfejsu API obietnicy, aby zapewnić, że długo trwające połączenie (lub opóźnione połączenie za pomocą $timeout) zostanie faktycznie ukończone przed wykonaniem .then()?

Kod

angular 
    .module('app', []) 
    .controller('ThenCtrl', ThenCtrl); 

function ThenCtrl($timeout, $q) { 
    var vm = this; 

    vm.items = []; 

    $q.when(pushA()).then(pushB()); 

    $timeout(pushA, 5000).then(pushB()); 

    function pushA() { 
    vm.items.push('A'); 
    } 

    function pushB() { 
    vm.items.push('B'); 
    } 
} 

Markup

<div ng-app="app"> 
    <div ng-controller="ThenCtrl as vm"> 
    {{vm.items}} 
    </div> 
</div> 

mam założyć skrzypce: https://jsfiddle.net/kan3c61t/

Odpowiedz

13

Nie wywoływać funkcje wewnątrz metod .then.

$q.when(pushA()).then(pushB); 
    //$q.when(pushA()).then(pushB()); 

    $timeout(pushA, 5000).then(pushB); 
    //$timeout(pushA, 5000).then(pushB()); 

Zamiast tego przekazuj funkcje jako argumenty do metody .then. Usługa $q będzie przechowywać te funkcje, które będą później wywoływane.

Sposób działania usługi $q polega na przechowywaniu argumentu metody .then jako funkcji, która ma zostać później wywołana. W tym przypadku usługa $q przechowywała wartość zwróconą przez pushB() z efektem ubocznym polegającym na natychmiastowym przepychaniu na macierz wartości B.

DEMO on JSFiddle

+0

To także całkiem ciekawe rozwiązanie. –

+2

Bardzo wyraźnie zaznaczone. Jaką różnicę mogą zrobić te pary nawiasów. – twip

+0

Bardzo mi to pomogło – Fergus

6

Tutaj jesteś. To, co zrobiłem, to zasadniczo dodana funkcja success w części kodu zgodnej z then.

$timeout(pushA, 5000).then(function(success) { 
    pushB() 
    }); 

Oto działa demo.

Można również dodać error function jak ten

$timeout(pushA, 5000).then(function(success) { 
    pushB() 
    },function(error){console.log("Error");}); 

Podczas poszukiwania tej odpowiedzi, doszedłem również po drugiej stronie to bardzo helpful link

+1

To doskonałe przypomnienie podstawowej struktury interfejsu API; Dziękuję Ci. – twip

4

Jak wspominają inni - Twój większym problemem jest to, że .then(promise) i nie .then(function).

Obietnice oznaczają wartość + czas. Jest to wynik wyniku już rozpoczętej operacji. Obietnica to wartość - then czeka na funkcji. Nie można "realizować obietnic po innej obietnicy" - ponieważ obietnica oznacza, że ​​operacja już się rozpoczęła.

Po then(x) dla funkcji innych niż funkcja jest ignorowana.Jest to niefortunny wybór w specyfikacji obietnic, ale musimy z tym żyć.

Ponieważ Twoje połączenia są synchroniczne, nie powinieneś używać do tego obietnic. Jeśli kod robi coś synchroniczne można sekwencji działań z ; i nie then:

pushA(); 
pushB(); 

Jeśli jest to wezwanie, które zwraca obietnice to po prostu staje się:

pushA().then(pushB); 

Nie ma sensu w nazywaniu $q.when który zamienia nie obietnice na obietnice.

że piszę to jako:

pushA(); 
$timeout(5000).then(pushB); 

Nie ma sensu, aby przekształcić pierwszy synchroniczne działanie na funkcję powracającego obietnicy lub zaangażować obietnic nigdzie z wyjątkiem timeout. Jeśli potrzebujesz pushA wydarzy po 5000ms że sama wciąż chyba napisać:

$timeout(5000).then(pushA).then(pushB) 

Ponieważ myślę, że jest bardziej czytelny i znowu nie wiążą pushA i pushB obietnicami bezpośrednio.

+0

Dziękuję za odpowiedź. Czasami bardzo trudno jest uchwycić intencje, będąc jednocześnie krótkimi i zrozumiałymi dla stanowisk SO. To, co próbowałem uchwycić, to scenariusz, w którym zamierzamy rozwiązać A przed B, a A jest obietnicą, która musi ponieść opóźnienie. Znaczenie: Chciałbym, aby 'pushA' wykonał swoją pracę, włączając w to opóźnienie, a następnie-i-tylko-, następnie wykonaj' pushB'. Oto zaktualizowane skrzypce, zaimplementowane z twoimi danymi wejściowymi, które pomogły mi dotrzeć do tego, czego szukałem: https://jsfiddle.net/nam3cbaw/1/ – twip