Con una promessa, perché i browser restituiscono un rifiuto due volte ma non una risoluzione due volte?


10

Ho problemi a capire javaScript promises. Ho scritto il seguente codice:

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

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

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

Lo vedo immediatamente nella mia console di sviluppo di Chrome: inserisci qui la descrizione dell'immagine

Ma dopo aver atteso 5 secondi, il messaggio diventa automaticamente nero come questa immagine: inserisci qui la descrizione dell'immagine

Non ho mai visto questo comportamento prima tra il mio codice javaScript e una console per sviluppatori, in cui il mio codice javaScript può "modificare il contenuto esistente" nella console per sviluppatori.

Quindi ho deciso di vedere se si verifica la stessa situazione resolvescrivendo questo codice:

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

    resolve("hello world");
});

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

Ma in questa situazione, la mia console per sviluppatori non mostra nulla fino a 5 secondi dopo, a cui stampa hello world.

Perché sono resolvee rejecttrattati in modo così diverso in termini di quando vengono invocati?


EXTRA

Ho anche scritto questo codice:

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

Ciò causa diversi output alla console per gli sviluppatori. Errore rosso all'ora 0, rosso diventa nero all'ora 5 secondi con il testo errors hello world, quindi un nuovo messaggio di errore all'ora 6 secondi errors 2 hello world, quindi un messaggio di errore rosso all'ora 7 secondi. Ora sono molto confuso su quante volte rejectviene effettivamente invocato ... Mi sono perso ...


1
Solo a parte: var p = new Promise(function(resolve,reject){ reject(Error("hello world")); });può essere più idiomaticamente e concisamente scritto come var p = Promise.reject(Error("hello world"));:-)
TJ Crowder

1
Domanda fantastica.
TJ Crowder,

Risposte:


11

Wow, è davvero bello. Non avevo mai visto la console farlo prima. (Ha altre forme di comportamento dinamico, quindi, quindi ...) Ecco cosa sta succedendo:

Nel primo caso, l'esecuzione del codice di tutto al di fuori setTimeoutdel codice di callback viene completata e lo stack di esecuzione ritorna in modo che sia in esecuzione solo il " codice piattaforma " (come lo specifica Promises / A +), non il codice JavaScript dell'utente (per il momento). A quel punto, la promessa viene respinta e nulla ha gestito il rifiuto, quindi è un rifiuto non gestito e devtools te lo segnala come tale.

Quindi , cinque secondi dopo, il callback viene eseguito e allega un gestore di rifiuto. A questo punto, il rifiuto non viene più gestito. Apparentemente, Chrome / V8 / devtools lavorano insieme per rimuovere l'avviso di rifiuto non gestito dalla console. Quello che vedi appare invece è quello che hai emesso nel tuo gestore di rifiuto tramite console.log. Se si collegasse prima il gestore del rifiuto, non si otterrebbe quell'errore di rifiuto non gestito.

Questo non accade con la realizzazione perché non gestirla non è una condizione di errore. Non gestire il rifiuto è.


1
Oh, ha senso. Ho notato che FireFox lo gestisce in modo leggermente diverso. Ma ok, ora ha più senso.
Giovanni

1
Ho scritto lo stesso in risposta, ma SO ha caricato il tuo, quindi non ho pubblicato il mio. Bella spiegazione! +1
FZ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.