Ich sehe die Dokumentation zu Bluebirds finally
, verstehe den Unterschied zu then
aber immer noch nicht ganz.
Um es klar auszudrücken: Ich weiß genau, warum then
nach einer catch
aufgerufen wird. Ich will es soll nach einem Fang aufgerufen werden. Das ist die Absicht. Meine Frage lautet: Wenn I want code unabhängig vom Versprechungsstatus immer ausgeführt werden soll, worin besteht der Unterschied zwischen then
und finally
?
Ich habe diesen Test gebaut:
var Promise = require("bluebird");
function test1 () {
console.log("RESOLVE + THEN + CATCH + THEN");
return new Promise((resolve, reject) => resolve())
.then(() => console.log("then"))
.catch(err => console.log("error:", err.message))
.then(() => console.log("end"));
}
function test2 () {
console.log("REJECT + THEN + CATCH + THEN");
return new Promise((resolve, reject) => reject(new Error("rejected")))
.then(() => console.log("then"))
.catch(err => console.log("error:", err.message))
.then(() => console.log("end"));
}
function test3 () {
console.log("RESOLVE + THEN + CATCH + FINALLY");
return new Promise((resolve, reject) => resolve())
.then(() => console.log("then"))
.catch(err => console.log("error:", err.message))
.finally(() => console.log("end"));
}
function test4 () {
console.log("REJECT + THEN + CATCH + FINALLY");
return new Promise((resolve, reject) => reject(new Error("rejected")))
.then(() => console.log("then"))
.catch(err => console.log("error:", err.message))
.finally(() => console.log("end"));
}
// run tests "sequentially" so console output doesn't get blended
setTimeout(test1, 500);
setTimeout(test2, 1000);
setTimeout(test3, 1500);
setTimeout(test4, 2000);
Dies testet vier Fälle:
.then(...).catch(...).then(...)
mit einem entschlossenen Versprechen..then(...).catch(...).then(...)
mit einem abgelehnten Versprechen..then(...).catch(...).finally(...)
mit einem entschlossenen Versprechen..then(...).catch(...).finally(...)
mit einem abgelehnten Versprechen.Die Ergebnisse, die ich sehe, sind Fälle 1 + 2, die sich identisch zu 3 + 4 verhalten: Das letzte Bit (then
oder finally
, je nach Test) wird ausgeführt, unabhängig davon, was vor ihm passiert, wie beabsichtigt. Die Ausgabe dieses Programms ist:
RESOLVE + THEN + CATCH + THEN
then
end
REJECT + THEN + CATCH + THEN
error: rejected
end
RESOLVE + THEN + CATCH + FINALLY
then
end
REJECT + THEN + CATCH + FINALLY
error: rejected
end
Der Grund, warum ich frage, ist, dass ich einen Kommentar zu dieser anderen Frage gesehen habe, die ich gestellt habe :
Nicht sicher, ob Ihre Versprechen dies unterstützen, aber Sie sollten den letzten
.then
in.finally
ändern, damit diebusy
immer gelöscht wird.
Aufgrund meiner sehr begrenzten Kenntnisse über then
und der obigen Tests scheint then
ausreichend zu sein. Aber nach diesem Kommentar frage ich mich und die Sicherheit der Verwendung von then
, um "finally" -Code auszuführen.
Meine Frage lautet also: Was ist der Unterschied zwischen then
und finally
? Sie sehen so aus, als ob sie sich gleich verhalten, aber wann müsste ich finally
anstelle von then
verwenden?
Erster Unterschied: Manchmal möchten Sie keine Fehler an der Stelle abfangen, an der sie auftreten, sondern im Code, der diese Funktion verwendet, damit Sie sie nicht abfangen. In diesem Fall können Sie then()
und finally()
nicht ersetzen.
Manchmal müssen Sie etwas aufräumen, ob ein Fehler aufgetreten ist oder nicht (Verweise auf Null setzen, Zeitüberschreitungen löschen usw.). Dort verwenden Sie finally()
.
Zweiter Unterschied: Die Funktion, die Sie an catch()
übergeben, könnte auch werfen, dann hätten Sie ein abgelehntes Promise und die folgende then()
würde nicht aufgerufen.
(also ein final bevor ein catch wird noch auf einen fehler ausgeführt, wußte das nicht)
Ja, das ist der Punkt von finally()
. Es wird unter allen Umständen ausgeführt, ohne den aufgelösten Wert zu ändern.
Vielleicht möchten Sie etwas über try {} finally {}
lesen/googleen, ohne zu fangen.
.then
und .finally
stimmen nicht überein.
.then
ist das Hauptversprechen. Es ist genau das, was in der Promises/A + spec definiert ist, und alle Versprechenbibliotheken werden es implementieren.
Ein Bluebird .finally
- Handler wird "unabhängig vom Schicksal des Versprechens" aufgerufen. Eine unbehandelte Ausnahme löst also immer noch einen .finally
aus.
new Promise((resolve, reject) => reject(false))
.finally(a => console.log('finally', a))
// finally undefined
// Unhandled rejection false
new Promise((resolve, reject) => reject(false))
.then(a => console.log('then', a))
// Unhandled rejection false
.finally
ändert den aufgelösten Wert des Versprechens nicht und erhält das Ergebnis der Versprechenkette nicht.
new Promise((resolve, reject) => reject(false))
.catch(e => {
console.log(e)
return 2
})
.finally(a => {
console.log('finally', a)
return 1
})
.then(res => console.log('res', res))
// finally undefined
// res 2
Die Methoden sehen in Ihren Testfällen ähnlich aus, da die Tests alle Fehler abfangen und Sie nur Versprechungen für die Flusskontrolle verwenden und sich nicht auf die Auflösung/Ablehnung der Werte entlang der Versprechenkette verlassen.
In Ordnung, nach ein paar Gesprächen und viel Hilfe von KevinB habe ich wenigstens einen Unterschied herausgefunden. Betrachten Sie die folgenden zwei neuen Tests:
function test5 () {
console.log("REJECT + THEN + CATCH/THROW + THEN");
return new Promise((resolve, reject) => reject(new Error("rejected")))
.then(() => console.log("then"))
.catch(function(err) { throw new Error("error in catch"); })
.then(() => console.log("end"));
}
function test6 () {
console.log("REJECT + THEN + CATCH/THROW + FINALLY");
return new Promise((resolve, reject) => reject(new Error("rejected")))
.then(() => console.log("then"))
.catch(function(err) { throw new Error("error in catch"); })
.finally(() => console.log("end"));
}
In diesen wird das Versprechen abgelehnt, aber es wird ein Fehler von catch
ausgegeben.
Das Versprechen wird letztendlich in beiden Fällen abgelehnt, aber für den Fall finally
wird die finally
noch ausgeführt, die then
nicht.
Also das ist der Unterschied. Sie sind fast - mit der einzigen Ausnahme, dass, wenn ein Fehler vomcatch
-Handler ausgegeben wird, finally
ausgeführt wird und then
dies nicht tut.
Das bedeutet, dass der Kommentar, den ich zitiert habe, auch Vorzüge hat: Wenn in meinem Fehlerbehandlungsprogramm ein anderer Fehler aufgetreten ist, würde eine then
keine Bereinigung garantieren, eine finally
jedoch. Das ist der Fall, den ich vermisst habe.