2015-03-17 21 views
10

Wciąż uczę się JavaScript Promise s, i natknąłem się na zachowanie, którego nie rozumiem.Obietnica JavaScript wtedy() zamawianie

var o = $("#output"); 
 
var w = function(s) { 
 
    o.append(s + "<br />"); 
 
} 
 

 
var p = Promise.resolve().then(function() { 
 
    w(0); 
 
}).then(function() { 
 
    w(1); 
 
}); 
 

 
p.then(function() { 
 
    w(2); 
 
    return new Promise(function(r) { 
 
     w(3); 
 
     r(); 
 
    }).then(function() { 
 
     w(4); 
 
    }); 
 
}).then(function() { 
 
    w(5); 
 
}); 
 

 
p.then(function() { 
 
    w(6); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="output"></div>

spodziewałbym te oświadczenia, aby uruchomić w porządku - to znaczy, że wynik byłby

0 
1 
2 
3 
4 
5 
6 

Zamiast tego, wyjście jest

0 
1 
2 
3 
6 
4 
5 

Nawet usunięcie wewnętrznego podajnika Promise s, co wydaje mi się być, sprzeczne wyniki. 1 jest wyprowadzane przed 2, ale 6 jest wyprowadzane przed 5.

Czy ktoś może mi to wyjaśnić?

Coś, co zauważyłem, to ponowne przydzielanie numeru p za każdym razem, gdy otrzymujemy zamówienie, którego oczekuję.

+0

Dlaczego oczekujesz tego zamówienia? Kolejność, w jakiej piszesz kod, niekoniecznie jest kolejnością, w której obietnice rozwiązują się; tylko "wtedy" ma nad tym kontrolę. – elclanrs

+0

Ponieważ oczekuję, że 'then()' zdarzy się w porządku. – dfoverdx

+1

Tak, "następnie" ** każdego ** łańcucha obietnic. – elclanrs

Odpowiedz

24

Powodem widać 6 wcześnie jest, bo nie łańcuch, to rozgałęziony.

Po wywołaniu p.then().then().then(), masz łańcuch obietnic, które musi wykonać w poprawnej kolejności.
Jeśli jednak zadzwonisz pod numer p.then().then(); p.then(), masz 2 obietnice dołączone do p - zasadniczo tworząc gałąź, a druga gałąź zostanie wykonana razem z pierwszą.

Można rozwiązać ten problem poprzez zapewnienie tworzenia łańcucha je razem p = p.then().then(); p.then();

FYI, prawie nigdy nie chcą oddziału, chyba że wprowadzą je ze sobą (np. Promise.all) lub są celowo tworząc „ogień i zapomnij” gałąź.

4

Co robi r()?

Zamawianie jest nieokreślone, ponieważ realizujesz tę samą obietnicę -> odnosi się to konkretnie do drugiego i trzeciego łańcucha.

Jeśli robiłeś, co następuje wtedy zamówienie może być zagwarantowane:

var p = Promise.resolve().then(function() { 
    w(0); 
}).then(function() { 
    w(1); 
}); 

// Key difference, continuing the promise chain "correctly". 
p = p.then(function() { 
    w(2); 
    return new Promise(function(r) { 
     w(3); 
     r(); 
    }).then(function() { 
     w(4); 
    }); 
}).then(function() { 
    w(5); 
}); 

p.then(function() { 
    w(6); 
}); 
+0

'r()' jest tylko funkcją 'resolve()' wewnętrznej Promise'a. Tak rozumiem poprawnie, że 'var p = Promise.resolve(); p.then (f1); p.then (f2); 'oznacza, że' f1() 'i' f2() 'zostaną zamówione, jednak silnik JS będzie się tak czuł? – dfoverdx

+1

@dfoverdx: Tak, 'p.then (f); p.then (g) 'nie jest tym samym co' p.then (f) .then (g) '. – elclanrs

+0

Dobra, rozumiem. Dzięki! – dfoverdx