2016-02-16 12 views
6

Nie jestem pewien, czy rozumiem różnicę między tymi dwoma typowymi scenariuszami.Różnica między zwrotem obietnicy a powrotem nieokreślonym w obietnicy

że mamy to:

user.save().then(function(val){ 
    anotherPromise1(val); 
}).then(function(val){ 
    anotherPromise2(val); 
}).catch(function(err){ 

}); 

kontra:

user.save().then(function(val){ 
    return anotherPromise1(val); 
}).then(function(val){ 
    return anotherPromise2(val); 
}).catch(function(err){ 

}); 

wiem, że to robi różnicę, ale jak dokładnie?

+0

przyjrzeć http://kctang.github.io/blog/2015/05/09/understanding-javascript-promise-with-examples-no-more-callback-hell, gdzie zapewnia kilka scenariuszy, w jaki sposób można wykorzystać obietnice. – kctang

+1

Wyszukaj * rozwiązując zagadkę * [tutaj] (http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html), znajdziesz sekcję, w której autor wizualnie pokazuje różnicę w czasie między kilkoma sposobami łączenia obietnic (w tym dwoma przykładami). – Shanoor

+0

Nie jesteś "w środku" obietnicy. Jesteś w funkcji (miejmy nadzieję) zwracając obietnicę. – jib

Odpowiedz

9

Jeśli nie zwrócisz wartości oddzwonienia then, skutecznie zwrócisz undefined. Następne wywołanie zwrotne then zostanie uruchomione natychmiast, a jako wartość rozdzielczości zostanie wyświetlona wartość undefined.

Jeśli wrócisz obietnicę od then zwrotnego, drugi then zwrotna czeka na tej obietnicy (pośrednio, ale to naprawdę nie ma znaczenia), a kiedy ta obietnica zostanie rozwiązany, pobiera wartość rozdzielczości z tej obietnicy.

(To jest objęte specyfikacją then w Promises/A+ spec, ale nieznacznie przez zaniechanie   — to wyraźnie nie wspomina, co powinno się zdarzyć, jeśli onFulfilled nic nie wróci, ale w JavaScripcie, wywołując funkcję zawsze daje wartość wynikowa, jeśli funkcja nie zwraca czegoś jawnie, wynikiem jest wywołanie undefined. JavaScript nie ma pojęcia void metody a'la C/C#/C++/Java.)

You można go zobaczyć w tym skrypcie live copy on Babel's REPL:

let start = Date.now(); 
function elapsed() { 
    let rv = String(Date.now() - start); 
    while (rv.length < 4) { 
    rv = "0" + rv; 
    } 
    return rv; 
} 
function anotherPromise(type, val) { 
    console.log(`${elapsed()}: anotherPromise[${type}] got ${val}`); 
    return new Promise(resolve => { 
    setTimeout(() => { resolve(val * 2); }, 1000); 
    }); 
} 
function anotherPromise2(type, val) { 
    console.log(`${elapsed()}: anotherPromise2[${type}] got ${val}`); 
    return new Promise(resolve => { 
    setTimeout(() => { resolve(val * 3); }, 10); 
    }); 
} 
let user = { 
    save:() => { 
    return new Promise(resolve => { 
     setTimeout(() => { 
     resolve(42); 
     }, 10); 
    }); 
    } 
} 

// Without return 
user.save().then(function(val){ 
    anotherPromise("without", val); 
}).then(function(val){ 
    anotherPromise2("without", val); 
}).then(function() { 
    console.log(`${elapsed()}: All done`); 
}).catch(function(err){ 
}); 

user.save().then(function(val){ 
    return anotherPromise("with", val); 
}).then(function(val){ 
    return anotherPromise2("with", val); 
}).then(function() { 
    console.log(`${elapsed()}: All done`); 
}).catch(function(err){ 
}); 

wyjście jest (na przykład):

 
0015: anotherPromise[without] got 42 
0017: anotherPromise2[without] got undefined 
0018: All done 
0020: anotherPromise[with] got 42 
1021: anotherPromise2[with] got 84 
1032: All done 

Uwaga: różnice między bez powrót i z powrót:

  • bez, anotherPromise2 był wywołane natychmiast (jak widać z wartości czasu, które upłynęły) i otrzymaliśmy undefined.

  • z, anotherPromise2 czekał anotherPromise 'rozdzielczości s występuje, i następnie otrzymane 84 (anotherPromise jest wartość rozdzielczości)

2

Różnica jest czas w tym zakresie.

W przykładzie 1, obietnica jest spełniona save i anotherPromise1 zostanie wywołany, a ponieważ nie ma obietnicy zwrócona, anotherPromise2 zostanie wywołany natychmiast.

Jeśli zwrócisz obietnicę funkcji anotherPromise1, nastąpi inwokacja anotherPromise, po rozwiązaniu problemu anotherPromise1.

Więc Przykład 1: anotherPromise1 i anotherPromise2 będzie kręcony jednoczesne Podczas Przykład 2: anotherPromise2 będzie czekać na anotherPromise1 zostać rozwiązane

+1

* "Tak więc przykład 1:' innyPromise1' i 'anotherPromise1' będą nagrywane jednocześnie" * Myślę, że chodziło Ci o "anotherPromise' i' anotherPromise2' "(nazwy OP nie były spójne). Nie, nie będą one jednoczesne, zostaną wykonane * w serii *, 'anotherPromise' następnie' anotherPromise2', z 'anotherPromise2' otrzymującą zwrotną wartość callback' onFulfilled' zawierającą 'anotherPromise'. Powiedziałeś to poprawnie na początku odpowiedzi, po prostu nie w podsumowaniu na końcu. Co więcej, istnieje ważna różnica w wartości rozdzielczości, jaką widzi "anotherPromise2", a nie tylko w czasie. –

+0

Tak, ja zredagowałem OP, aby mieć spójne nazwy –