Warum kann ich nicht innerhalb werfen ein Versprechen.catch-handler?
Warum kann ich nicht einfach werfen ein Error
im catch-Rückruf und lassen Sie den Prozess, den Fehler so behandeln, als ob es in jedem anderen Bereich?
Wenn ich es nicht tun console.log(err)
wird nichts ausgedruckt, und ich weiß nichts über das, was passiert ist. Der Prozess endet nur...
Beispiel:
function do1() {
return new Promise(function(resolve, reject) {
throw new Error('do1');
setTimeout(resolve, 1000)
});
}
function do2() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
reject(new Error('do2'));
}, 1000)
});
}
do1().then(do2).catch(function(err) {
//console.log(err.stack); //This is the only way to see the stack
throw err; //This does nothing
});
Wenn callbacks, die ausgeführt werden, in dem Haupt-thread, warum die Error
wird verschluckt von einem schwarzen Loch?
Es wird nicht verschluckt durch ein Schwarzes Loch. Er lehnt die Versprechen, dass
Siehe auch Warum sind Ausnahmen verwendet für die Ablehnung verspricht in JS? und Wie kann ich das behandeln von Ausnahmen weltweit mit native verspricht in io.js / node.js?
statt
.catch(…)
gibt.Siehe auch Warum sind Ausnahmen verwendet für die Ablehnung verspricht in JS? und Wie kann ich das behandeln von Ausnahmen weltweit mit native verspricht in io.js / node.js?
statt
.catch((e) => { throw new Error() })
schreiben .catch((e) => { return Promise.reject(new Error()) })
oder einfach .catch((e) => Promise.reject(new Error()))
InformationsquelleAutor demian85 | 2015-06-08
Du musst angemeldet sein, um einen Kommentar abzugeben.
Als andere haben erklärt, das "schwarze Loch", weil das werfen innerhalb einer
.catch
weiterhin wird die Kette mit einem abgelehnt Versprechen, und Sie haben keine mehr fängt, was zu einem ungekündigten Kette, die Schwalben Fehler (schlecht!)Fügen Sie eine weitere zu fangen um zu sehen was passiert:
Einen Haken in der Mitte der Kette ist nützlich, wenn Sie wollen die Kette zu gehen, die trotz einer fehlgeschlagenen Schritt, aber ein re-throw ist nützlich, um weiterhin scheitern nach Dinge zu tun, wie die Protokollierung von Informationen oder cleanup-Schritte, vielleicht sogar zu verändern, die Fehler ausgelöst.
Trick
Machen den Fehler zeigen sich als ein Fehler in der web-Konsole, als Sie es ursprünglich beabsichtigt war, habe ich diesen trick verwenden:
Sogar die Zeilennummern überleben, so dass der link in der web-Konsole bringt mich direkt zu der Datei und Zeile, wo die (original -) Fehler passiert ist.
, Warum es funktioniert
Jede Ausnahme in einer Funktion, die aufgerufen wird, als ein Versprechen der Erfüllung oder Ablehnung handler wird automatisch umgewandelt, um eine Absage an das Versprechen, das man haben soll, um zurückzukehren. Das Versprechen-code ruft die Funktion kümmert sich um diese.
Einer Funktion, die aufgerufen wird, die von setTimeout auf der anderen Seite, läuft immer von JavaScript stabilen Zustand, d.h. es läuft in einem neuen Zyklus in die JavaScript-event-Schleife. Ausnahmen gibt es nicht fing, indem Sie alles, und stellen Sie es auf der web-Konsole. Da
err
enthält alle Informationen über den Fehler, inklusive der original-stack, der Datei und der Zeilennummer, es wird immer noch korrekt gemeldet.Über den trick: Sie werfen sind, weil Sie wollen, um zu melden, also warum nicht melden Sie sich einfach direkt? Dieser trick wird bei einem "zufälligen" Zeitpunkt werfen uneinholbar Fehler.... Aber die ganze Idee von Ausnahmen (und die Art und Weise verspricht, mit Ihnen umzugehen), ist es die Anrufer obliegt, um den Fehler abzufangen und mit Ihr umgehen. Dieser code effektiv macht es unmöglich, den Anrufer zum Umgang mit den Fehlern. Warum nicht einfach machen, eine Funktion zu handhaben ist es für Sie?
function logErrors(e){console.error(e)}
dann verwenden Sie es wiedo1().then(do2).catch(logErrors)
. Die Antwort selbst ist große btw, +1Ich Schreibe eine AWS lambda-enthält viele Versprechungen verbunden, die mehr oder weniger wie in diesem Fall. Zu nutzen AWS Alarme und Benachrichtigungen im Falle von Fehlern, die ich brauche, um die lambda-crash auslösen eines Fehlers (vermute ich mal). Ist der trick, der einzige Weg, um diese zu erhalten?
In meinem Fall, ich versuche zu senden, Fehler-details zu meinem server in
window.onerror
event-handler. Nur, indem Sie diesetTimeout
trick kann dies getan werden. Ansonstenwindow.onerror
werden nie hören eine Sache, über die Fehler, die in Versprechen.Immer noch, ob es
console.log
oderpostErrorToServer
können Sie genau das tun, was getan werden muss. Es gibt keinen Grund, was auch immer code ist inwindow.onerror
kann nicht zerlegt werden in eine separate Funktion und aufgerufen werden, von 2 Orten. Es ist wahrscheinlich sogar kürzer als diesetTimeout
Linie.InformationsquelleAutor jib
Wichtige Dinge zu verstehen, hier
Sowohl die
then
undcatch
Funktionen return new promise-Objekte.Entweder werfen oder explizit ablehnen, bewegen sich die aktuellen Versprechen an den Staat abgelehnt.
Seit
then
undcatch
Gegenzug neue Objekte Versprechen, Sie können verkettet werden.Wenn Sie werfen oder ablehnen innen ein Versprechen handler (
then
odercatch
), es wird behandelt in die nächste Ablehnung handler unten die Verkettung Pfad.Erwähnt jfriend00, die
then
undcatch
Handler sind nicht synchron ausgeführt. Wenn ein handler wirft, wird es zu einem Ende kommen sofort. So, der Stapel wird abgewickelt, und die Ausnahme, verloren wären. Deshalb ist das werfen einer Ausnahme lehnt die aktuellen Versprechen.In Ihrem Fall, Sie lehnen innerhalb
do1
durch das werfen einerError
Objekt. Nun, die aktuellen Versprechen werden abgelehnt, Staat und Steuerung übertragen werden, an den nächsten handler, diethen
in unserem Fall.Da die
then
handler nicht über ein ablehnungs-handler, diedo2
wird nicht überhaupt ausgeführt werden. Sie können dies überprüfen, indem mitconsole.log
drin. Da die derzeitigen Versprechen nicht ein ablehnungs-handler, wird es auch abgelehnt mit der Ablehnung Wert aus dem vorherigen Versprechen und die Kontrolle übertragen wird an den nächsten handler, diecatch
.Als
catch
ist eine Ablehnung handler, wenn Sieconsole.log(err.stack);
im inneren, Sie sind in der Lage, um zu sehen, den Fehler-stack-trace. Jetzt sind Sie werfen eineError
- Objekt aus, so das Versprechen zurückgegebencatch
werden auch die Ablehnung Zustand.Da nicht angebracht, eine etwaige Ablehnung handler zu
catch
Sie sind nicht in der Lage zu beobachten, die Ablehnung.Können Sie split-die Kette und das besser verstehen, wie diese
Die Ausgabe, die Sie erhalten, sind so etwas wie
Innerhalb der
catch
hf 1, Sie werden immer den Wertpromise
Objekt als abgelehnt.Gleichen Weise, die Versprechen Rückgabe durch die
catch
hf 1, ist ebenfalls abgelehnt mit dem gleichen Fehler, mit denen diepromise
wurde abgelehnt, und wir beobachten es in der zweitencatch
hf..then()
Handler sind async (stack abgewickelt, bevor Sie ausgeführt werden), so dass Ausnahmen in Ihnen haben sich in absagen, sonst gäbe es keine exception-Handler, um Sie zu fangen.InformationsquelleAutor thefourtheye
Ich habe versucht, die
setTimeout()
Methode siehe oben...Störend, ich fand das völlig unüberprüfbare. Denn es wirft ein asynchroner Fehler, können Sie nicht wickeln Sie es in ein
try/catch
- Anweisung, weil diecatch
haben, aufgehört haben, von der Zeit, die Fehler ausgelöst.Ich wieder nur mit einem Zuhörer, die perfekt funktioniert und weil es ist, wie JavaScript verwendet werden soll, war sehr prüfbar.
InformationsquelleAutor RiggerTheGeek
Laut der spec (siehe 3.III.d):
Dass bedeutet, dass wenn Sie werfen exception in
then
Funktion, wird es gefangen werden und Ihre Versprechen werden abgelehnt.catch
keinen Sinn hier, es ist nur Verknüpfung zu.then(null, function() {})
Ich denke, Sie möchten, melden Sie unbehandelte Ablehnungen in Ihrem code. Die meisten Versprechen Bibliotheken feuert eine
unhandledRejection
. Hier ist relevanten gist mit Diskussion darüber.unhandledRejection
Haken ist bei server-side JavaScript auf der client-Seite verschiedene Browser haben verschiedene Lösungen. WIR haben nicht standardisiert, es noch nicht, aber es ist langsam, aber sicher.InformationsquelleAutor just-boris
Ich weiß, das ist ein bisschen spät, aber ich stieß auf diesen thread, und keine der Lösungen waren einfach zu implementieren und zu mir, also kam ich mit meinem eigenen:
Habe ich noch eine kleine Hilfsfunktion, die eine Zusage zurückgibt, etwa so:
Dann, wenn ich einen bestimmten Ort in alle meine Versprechen Kette wo ich will, einen Fehler auslösen (und lehnen das Versprechen), dass ich einfach wieder aus der obigen Funktion mit meinem konstruierten Fehler, etwa so:
Diese Weise bin ich in die Kontrolle des werfenden extra Fehler aus dem inneren der Versprechen-Kette. Wenn Sie möchten, auch mit 'normalen' promise Fehler, Sie erweitern Ihren Fang zu behandeln, das 'selbst-geworfen' Fehler getrennt.
Hoffe, das hilft, es ist meine erste stackoverflow-Antwort!
InformationsquelleAutor nuudles
Ja verspricht schlucken Fehler, und Sie können nur fangen Sie mit
.catch
, wie erläutert, mehr im detail in anderen Antworten. Wenn Sie in Node.js und möchten Sie zum reproduzieren des normalenthrow
Verhalten, Druck-stack-trace in der Konsole, und beenden Prozess, die Sie tun können,unhandledRejection
eventJa, das ist vorausgesetzt, dass Sie die Kette Ihre Versprechungen so, die Ausfahrt ist die Letzte Funktion, und es ist nicht heute nach. Die Veranstaltung, die Sie erwähnen, ich denke, es ist nur bei der Verwendung von Bluebird.
Bluebird, Q, wenn, native verspricht, ... Es wird wahrscheinlich ein standard werden.
InformationsquelleAutor Jesús Carrera