2014-12-31 9 views
173

Jaka jest różnica pomiędzy:Jaka jest różnica pomiędzy wartością lub Promise.resolve powracającego z potem()

new Promise(function(res, rej) { 
 
    res("aaa"); 
 
    }) 
 
    .then(function(result) { 
 
    return "bbb"; 
 
    }) 
 
    .then(function(result) { 
 
    console.log(result); 
 
    });

i tak:

new Promise(function(res, rej) { 
 
    res("aaa"); 
 
    }) 
 
    .then(function(result) { 
 
    return Promise.resolve("bbb"); 
 
    }) 
 
    .then(function(result) { 
 
    console.log(result); 
 
    });

Pytam, ponieważ otrzymuję inne zachowanie, używając usługi Angular i $ http z łańcuchem .then(). Trochę za dużo kodu stąd pierwszy przykład powyżej.

+1

Jakie "inne zachowanie" widzisz? Oba przykłady powinny działać i zachowywać się w przybliżeniu tak samo. "Promise.resolve()" w drugim przykładzie jest niepotrzebne. – JLRishe

+4

@pixelbits Nie ma nic złego w zwracaniu obietnicy od handlarza 'ów', w rzeczywistości jest to kluczowy aspekt specyfikacji obietnic, że możesz to zrobić. –

+0

Należy zauważyć, że działa to z arbitralnie zagnieżdżonymi 'then's - termin" inne języki "dla tego jest taki, że' then' jest jednocześnie 'mapą' i' flatMap'. –

Odpowiedz

60

Oba przykłady powinny zachowywać się tak samo.

Wartość zwrócona wewnątrz funkcji obsługi then() staje się wartością rozdzielczości obietnicy zwróconej z tego then(). Jeśli wartość zwrócona wewnątrz .then jest obietnicą, obietnica zwrócona przez then() "przyjmie stan" tej obietnicy i rozwiąże/odrzuci tak, jak zrobi to obiecana obietnica.

W swoim pierwszym przykładzie wrócisz "bbb" w pierwszym then() obsługi, więc "bbb" przechodzi do następnego then() obsługi.

W drugim przykładzie zwracana jest obietnica, która jest natychmiast rozwiązywana z wartością "bbb", więc "bbb" jest przekazywana do następnej procedury obsługi. (The Promise.resolve() tutaj jest obcy).

Wynik jest taki sam.

Jeśli możesz pokazać nam przykład, który faktycznie wykazuje inne zachowanie, możemy Ci powiedzieć, dlaczego tak się dzieje.

90

Zasadą jest, jeśli funkcja, która znajduje się w przewodnika then zwraca wartość, obietnica rozwiązuje/odrzuca z tą wartością, a jeśli funkcja zwraca obietnicę, co się dzieje, następna then klauzula będzie then klauzula obietnicy funkcja zwróciła, więc w tym przypadku pierwszy przykład przechodzi przez normalną sekwencję thens i wypisuje wartości, jak można by oczekiwać, w drugim przykładzie, obiekt obietnicy, który zostanie zwrócony, gdy wykonasz Promise.resolve("bbb") 's to jest then, który jest wywoływany podczas łączenia (dla wszystkich celów i celów). Sposób, w jaki faktycznie działa, opisano bardziej szczegółowo poniżej.

Cytowanie z Promises/A + specyfikacji: Procedura rozdzielczości

Obietnica jest praca przy streszczenie na wejściu obiecujące i wartość, co oznaczamy jako [[Resolve]](promise, x). Jeśli opcja x jest dostępna, próbuje wprowadzić obietnicę: przyjmuje stan, przy założeniu, że x zachowuje się co najmniej w pewnym stopniu jak obietnica. W przeciwnym razie spełnia obietnicę o wartości x.

Takie traktowanie zbiorów pozwala obiecującym implementacjom na współdziałanie, pod warunkiem, że ujawnią w tym przypadku metodę Promises/A +. Pozwala także implementacjom Promises/A + do "asymilowania" niezgodnych implementacji za pomocą rozsądnych metod.

Kluczową rzeczą, aby zauważyć tutaj jest ta linia:

jeśli x jest obietnica, przyjąć swój stan [3.4]

Link: https://promisesaplus.com/#point-49

+2

"Przyjmij jego stan" jest zwięzłym i użytecznym sposobem wyrażenia zachowania, gdy 'then' handler zwraca obietnicę. +1 dla referencji spec. –

+40

Właściwie - istotną częścią specyfikacji jest to, że '[[Rozstrzygnij]]' jest wywoływane zarówno na 'then'ables i wartościach, więc zasadniczo zawija wartość z obietnicą, więc' return "aaa" 'jest takie samo jako 'return Promise.resolve (" aaa ")' i 'return Promise.resolve (" aaa ")' jest tym samym, co 'return Promise.resolve (Promise.resolve (" aaa "))' - ponieważ resolve to idempotent calling to na wartości więcej niż jeden raz ma taki sam wynik. –

+5

@Benjamin Gruenbaum oznacza, że ​​powrót '" aaa "' i 'return Promise.resolve (" aaa ")' są wymienne w 'then'ables w każdym przypadku? – CSnerd

35

You już dostałem dobrą formalną odpowiedź. Pomyślałem, że powinienem dodać krótki.

Następujące rzeczy są identyczne z Promises/A+ obietnic:

  • Wywołanie Promise.resolve (w Twojej przypadku kątowy, który jest $q.when)
  • Wywołanie konstruktora obietnicy i rozwiązywaniu jego rezolwerem. W twoim przypadku jest to new $q.
  • Zwracanie wartości z wywołania zwrotnego then.
  • Wywołanie Promise.all na tablicy z wartością, a następnie wyodrębnienie tej wartości.

Więc następujące są identyczne za obietnicę lub zwykły wartości X:

Promise.resolve(x); 
new Promise(function(resolve, reject){ resolve(x); }); 
Promise.resolve().then(function(){ return x; }); 
Promise.all([x]).then(function(arr){ return arr[0]; }); 

I nic dziwnego, specyfikacja obietnice bazuje na Promise Resolution Procedure który umożliwia łatwe współdziałanie między bibliotekami (jak $ q i rodzime obietnice) i ułatwia ogólne życie. Za każdym razem, gdy może dojść do rozwiązania obietnicy, następuje rozwiązanie, które zapewnia ogólną spójność.

12

w prosty sposób, wewnątrz funkcji then Handler:

A) przy x jest wartością (liczba, łańcuch itp)

  1. return x odpowiada return Promise.resolve(x)
  2. throw x jest odpowiednikiem return Promise.reject(x)

B) Kiedy x to obietnica, która jest już rozstrzygnięty (nie czeka już):

  1. return x jest równoważna return Promise.resolve(x), czy obietnica została już rozwiązana.
  2. return x jest odpowiednikiem return Promise.reject(x), jeśli obietnica została już odrzucona.

c) gdy x jest Promise że czeka:

  1. return x powróci do kolejki Promise i będzie oceniane na kolejnym then.

Przeczytaj więcej na ten temat na stronie Promise.prototype.then() docs.

Powiązane problemy