Warum geben Browser bei einem Versprechen zweimal eine Ablehnung zurück, aber nicht zweimal eine Lösung?


10

Ich habe Probleme, JavaScript zu verstehen promises. Ich habe folgenden Code geschrieben:

var p = new Promise(function(resolve,reject){

    reject(Error("hello world"));
});

setTimeout(()=>p.catch(e=>console.log(e)),5000);

Ich sehe dies sofort in meiner Chrome-Entwicklerkonsole: Geben Sie hier die Bildbeschreibung ein

Aber nachdem ich 5 Sekunden gewartet habe, ändert sich die Nachricht automatisch in Schwarz wie in diesem Bild: Geben Sie hier die Bildbeschreibung ein

Ich habe dieses Verhalten noch nie zwischen meinem JavaScript-Code und einer Entwicklerkonsole gesehen, bei der mein JavaScript-Code "vorhandene Inhalte ändern" kann.

Also habe ich mich entschlossen, resolvedurch Schreiben dieses Codes zu prüfen, ob die gleiche Situation auftritt :

var p = new Promise(function(resolve,reject){

    resolve("hello world");
});

setTimeout(()=>p.then(e=>console.log(e)),5000);

In dieser Situation zeigt meine Entwicklerkonsole jedoch erst 5 Sekunden später etwas an, auf das sie dann druckt hello world.

Warum werden die resolveund rejectso unterschiedlich behandelt, wenn sie aufgerufen werden?


EXTRA

Ich habe auch diesen Code geschrieben:

var p = new Promise(function(resolve,reject){

    reject(Error("hello world"));
});

setTimeout(()=>p.catch(e=>console.log("errors",e)),5000);
setTimeout(()=>p.catch(e=>console.log("errors 2",e)),6000);
setTimeout(()=>p.catch(null),7000);

Dies führt zu mehreren Ausgaben an die Entwicklerkonsole. Roter Fehler zum Zeitpunkt 0, Rot wechselt zum Zeitpunkt 5 Sekunden mit dem Text zu Schwarz errors hello world, dann eine neue Fehlermeldung zum Zeitpunkt 6 Sekunden errors 2 hello world, dann eine rote Fehlermeldung zum Zeitpunkt 7 Sekunden. Jetzt bin ich sehr verwirrt darüber, wie oft ein rejecttatsächlich aufgerufen wird ... Ich bin verloren ...


1
Nur zur Seite: var p = new Promise(function(resolve,reject){ reject(Error("hello world")); });kann idiomatischer und prägnanter geschrieben werden als var p = Promise.reject(Error("hello world"));:-)
TJ Crowder

1
Tolle Frage.
TJ Crowder

Antworten:


11

Wow, das ist echt cool. Ich hatte noch nie zuvor gesehen, dass die Konsole das tat. (Es hat jedoch andere Formen von dynamischem Verhalten, also ...) Folgendes ist los:

Im ersten Fall wird die Codeausführung von allem außerhalb setTimeoutdes Rückrufcodes abgeschlossen und der Ausführungsstapel wird zurückgegeben, sodass nur " Plattformcode " (wie es die Promises / A + -Spezifikation nennt) ausgeführt wird, im Moment kein Userland-JavaScript-Code. Zu diesem Zeitpunkt wird das Versprechen abgelehnt und nichts hat die Ablehnung behandelt. Es handelt sich also um eine unbehandelte Ablehnung, und devtools meldet sie Ihnen als solche.

Dann fünf Sekunden später Ihr Rückruf läuft und fügt eine Ablehnung Handler. Ab diesem Zeitpunkt wird die Ablehnung nicht mehr unbehandelt. Anscheinend arbeiten Chrome / V8 / devtools zusammen, um die unbehandelte Ablehnungswarnung von der Konsole zu entfernen . Stattdessen wird angezeigt, was Sie in Ihrem Ablehnungshandler über ausgeben console.log. Wenn Sie den Ablehnungshandler früher anhängen, wird dieser nicht behandelte Ablehnungsfehler nicht angezeigt.

Dies geschieht nicht bei der Erfüllung, da die Nichtbehandlung der Erfüllung keine Fehlerbedingung ist. Ablehnung nicht zu behandeln ist.


1
Oh, das macht Sinn. Ich habe festgestellt, dass FireFox etwas anders damit umgeht. Aber ok, macht jetzt mehr Sinn.
John

1
Ich habe genauso als Antwort geschrieben, aber SO hat deine geladen, also habe ich meine nicht gepostet. Schöne Erklärung! +1
FZs
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.