2016-06-23 6 views
2

Ich möchte 3 Versprechen miteinander verketten, aber es gibt etwas Verhalten, das ich über die resolve und reject Funktionalität nicht herausfinden kann. Ich habe meinen Code vereinfacht, um die Frage zu stellen:Verkettung Versprechen in nativem Javascript

function testP(num) { 
    return new Promise((resolve, reject) => { 
    console.log('Do Work', num); 
    reject(num); 
    }); 
} 

function testPromises() { 
    return new Promise((resolve, reject) => { 
     testP(1) 
     .then(testP(2)) 
     .then(testP(3)) 
     .then(resolve) 
     .catch(reject); 
    }); 
}; 

const theTest = testPromises().then(()=>{ 
    console.log("all done"); 
}).catch(err => { 
    console.log("ERR", err); 
}); 

Und was ich in meiner Ausgabe zu sehen ist:

Do Work 1 
Do Work 2 
Do Work 3 
ERR 1 

Warum wird der Code erhalten zu Do Work 2 und Do Work 3 wenn die ersten Versprechen Treffer reject sofort? Mein Verständnis war, dass die then Funktionen warten auf das Versprechen zu resolve oder reject vor der Ausführung.

+2

BTW 'return new Promise ((resolve, ablehnen) => {smth () .dann (smth2) .dann (auflösen) .catch (ablehnen); }) 'ist Antipattern. Es ist viel besser, 'return smth(). Then (smth2);'. –

Antwort

5

Denn wenn Sie tun

.then(testP(2)) 

Sie AnruftestP sofort und bedingungslos, in 2 vorbei, und dann den Rückgabewert in .then passieren, genau so, wie foo(bar())Anrufebar und übergibt den Rückgabewert in foo.

Dieser Code:

testP(1) 
    .then(testP(2)) 
    .then(testP(3)) 
    .then(resolve) 
    .catch(reject); 

wird folgendermaßen ausgewertet (einige kleinere Details weggelassen):

  • Anruf testP mit dem Wert 1 und erinnere mich an den sich ergebenden Wert als p1
  • Anruf testP mit der Wert 2
  • Anruf p1.then mit dem Ergebnis dieser Anruf und Erinnerung r der resultierende Wert als P2
  • Anruf testP mit dem Wert 3
  • Anruf p2.then mit dem Ergebnis dieses Anrufs und daran denken, die sich ergebende Wert als p3
  • Anruf p3.then mit dem Wert resolve und erinnern das Ergebnis als p4
  • Anruf p4.catch mit dem Wert reject
  • aufrufen reject Funktion aus dem ersten Aufruf von testP mit dem Wert 1
  • Rufen Sie den reject von testPromises mit dem Wert 1

Wenn Sie möchten, dass testP warten, bis der erste erledigt ist, müssen Sie nicht Anruf es, Sie einen Verweis auf sie passieren:

.then(testP) 

Wenn Sie es möchten, ein Argument in gebacken haben, verwenden bind:

.then(testP.bind(null, 2)) 

oder eine Inline-Funktion:

.then(function() { 
    return testP(2); 
}) 

Beispiel (erfordert einen Browser mit Promise):

function testP(num) { 
 
    return new Promise((resolve, reject) => { 
 
    console.log('Do Work', num); 
 
    reject(num); 
 
    }); 
 
} 
 

 
function testPromises() { 
 
    return new Promise((resolve, reject) => { 
 
     testP(1) 
 
     .then(testP.bind(null, 2)) 
 
     .then(testP.bind(null, 3)) 
 
     .then(resolve) 
 
     .catch(reject); 
 
    }); 
 
}; 
 

 
const theTest = testPromises().then(()=>{ 
 
    console.log("all done"); 
 
}).catch(err => { 
 
    console.log("ERR", err); 
 
});

+0

Es ist erwähnenswert, dass ein Nicht-Funktionstyp, der an "then" übergeben wird, Unsinn ist und nur ignoriert wird (da "testP (2)" zu einem "Versprechen" ausgewertet wird) – ftor