Dlaczego w przypadku obietnicy przeglądarki dwukrotnie zwracają odrzucenie, ale dwukrotnie nie rozwiązują problemu?

10

Mam problem ze zrozumieniem javaScript promises. Napisałem następujący kod:

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

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

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

Od razu widzę to w mojej konsoli programisty Chrome: wprowadź opis zdjęcia tutaj

Ale po odczekaniu 5 sekund wiadomość automatycznie zmienia kolor na czarny, jak na tym obrazku: wprowadź opis zdjęcia tutaj

Nigdy wcześniej nie widziałem takiego zachowania między moim kodem javaScript a konsolą programisty, gdzie mój kod javaScript może „modyfikować istniejącą zawartość” w konsoli programisty.

Postanowiłem więc sprawdzić, czy występuje taka sama sytuacja resolve, pisząc ten kod:

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

    resolve("hello world");
});

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

Ale w tej sytuacji moja konsola programisty nie pokazuje niczego, aż 5 sekund później, a następnie drukuje hello world.

Dlaczego są tak traktowane resolvei rejecttraktowane w różny sposób, gdy są wywoływane?


DODATKOWY

Napisałem również ten kod:

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);

Powoduje to kilka wyników w konsoli programisty. Czerwony błąd w czasie 0, czerwony zmienia się na czarny w czasie 5 sekund z tekstem errors hello world, następnie nowy komunikat o błędzie w czasie 6 sekund errors 2 hello world, a następnie czerwony komunikat o błędzie w czasie 7 sekund. Teraz jestem bardzo zdezorientowany, ile razy rejectfaktycznie wywoływane ... Jestem zagubiony ...

Jan
źródło
1
Na marginesie: var p = new Promise(function(resolve,reject){ reject(Error("hello world")); });można bardziej idiomatycznie i zwięźle napisać jako var p = Promise.reject(Error("hello world"));:-)
TJ Crowder,
1
Niesamowite pytanie.
TJ Crowder

Odpowiedzi:

11

Wow, to naprawdę fajne. Nigdy wcześniej nie widziałem, żeby konsola to robiła. (Ma inne formy zachowania dynamicznego, więc ...) Oto, co się dzieje:

W pierwszym przypadku wykonanie kodu wszystkiego poza setTimeoutkodem wywołania zwrotnego zostaje zakończone, a stos wykonania jest zwracany, tak więc działa tylko „ kod platformy ” (jak to nazywa specyfikacja Promises / A +), a nie kod JavaScript użytkownika (na razie). W tym momencie obietnica zostaje odrzucona i nic nie poradziło sobie z odrzuceniem, więc jest to nieobsługiwane odrzucenie i devtools zgłasza je jako takie.

Następnie , pięć sekund później, Twoje wywołanie zwrotne uruchamia się i dołącza moduł obsługi odrzucania. W tym momencie odrzucenie nie jest już obsługiwane. Najwyraźniej Chrome / V8 / devtools działają razem, aby usunąć nieobsługiwane ostrzeżenie o odrzuceniu z konsoli. Zamiast tego wyświetla się to, co wyświetlasz w module obsługi odrzucaniaconsole.log . Jeśli wcześniej podłączysz moduł obsługi odrzucania, nie otrzymasz tego nieobsługiwanego błędu odrzucenia.

Nie dzieje się tak w przypadku spełnienia, ponieważ brak obsługi spełnienia nie jest warunkiem błędu. Brak obsługi odrzucenia.

TJ Crowder
źródło
1
To ma sens. Zauważyłem, że FireFox traktuje to nieco inaczej. Ale ok, teraz ma to większy sens.
Jan
1
W odpowiedzi napisałem to samo, ale SO załadowałem twoje, więc nie opublikowałem mojego. Ładne wyjaśnienie! +1
FZs,