Con una promesa, ¿por qué los navegadores devuelven un rechazo dos veces pero no una resolución dos veces?

10

Tengo problemas para entender javaScript promises. Escribí el siguiente código:

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

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

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

Inmediatamente veo esto en mi consola de desarrollador de Chrome: ingrese la descripción de la imagen aquí

Pero después de esperar 5 segundos, el mensaje cambia automáticamente a negro como esta imagen: ingrese la descripción de la imagen aquí

Nunca antes había visto este comportamiento entre mi código javaScript y una consola de desarrollador, donde mi código javaScript puede "modificar el contenido existente" en la consola de desarrollador.

Así que decidí ver si ocurre la misma situación resolveescribiendo este código:

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

    resolve("hello world");
});

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

Pero en esta situación, mi consola de desarrollador no muestra nada hasta 5 segundos después, a lo que luego imprime hello world .

¿Por qué las resolvey rejecttratada de manera diferente en términos de cuando se invocan?


EXTRA

También escribí este código:

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

Esto provoca varias salidas a la consola del desarrollador. Error rojo en el tiempo 0, rojo cambia a negro en el tiempo 5 segundos con el texto errors hello world, luego un nuevo mensaje de error en el tiempo 6 segundos errors 2 hello world, luego un mensaje de error rojo en el tiempo 7 segundos. Ahora estoy muy confundido acerca de cuántas veces rejectse invoca realmente ... Estoy perdido ...

Juan
fuente
1
Solo un aparte: var p = new Promise(function(resolve,reject){ reject(Error("hello world")); });puede escribirse de manera más idiomática y concisa como var p = Promise.reject(Error("hello world"));:-)
TJ Crowder
1
Impresionante pregunta.
TJ Crowder

Respuestas:

11

Wow, eso es realmente genial. Nunca había visto a la consola hacer eso antes. (Sin embargo, tiene otras formas de comportamiento dinámico, así que ...) Esto es lo que está sucediendo:

En el primer caso, la ejecución del código de todo lo que está fuera setTimeoutdel código de devolución de llamada se completa y la pila de ejecución regresa de modo que solo " código de plataforma se está ejecutando el " (como lo llama la especificación Promises / A +), no el código JavaScript del usuario (por el momento). En ese punto, la promesa es rechazada y nada ha manejado el rechazo, por lo que es un rechazo no manejado y devtools se lo informa como tal.

Luego , cinco segundos después, su devolución de llamada se ejecuta y adjunta un controlador de rechazo. En este punto, el rechazo ya no se maneja. Aparentemente, Chrome / V8 / devtools trabajan juntos para eliminar la advertencia de rechazo no controlada de la consola. En cambio, lo que ves es lo que publicas en tu controlador de rechazo console.log. Si adjuntaste el controlador de rechazo antes, no obtendrías ese error de rechazo no controlado.

Esto no sucede con el cumplimiento porque no manejar el cumplimiento no es una condición de error. No manejar el rechazo es.

TJ Crowder
fuente
1
Oh eso tiene sentido. Noté que Firefox lo maneja de manera ligeramente diferente. Pero bueno, tiene más sentido ahora.
John
1
Escribí exactamente lo mismo en respuesta, pero SO cargó el tuyo, así que no he publicado el mío. Buena explicación! +1
FZs