javascript - sincronas - promises examples js
¿Por qué es posible pasar un parámetro no funcional a Promise.then() sin causar un error? (3)
Tengo lo siguiente:
new Promise(resolve => setTimeout(resolve, 2000))
.then(() => console.log("after 2 seconds"));
new Promise(resolve => setTimeout(resolve, 3000))
.then(console.log("before 3 seconds (instantly)"));
que produce el siguiente resultado:
> node index.js
before 3 seconds (instantly)
after 2 seconds
Promise.then () espera una función onFulfilled
, pero pasé en console.log("before 2 seconds (instantly)")
, que no es una función. Pregunta de dos partes:
- ¿Por qué
console.log("before 2 seconds (instantly)")
se ejecuta de inmediato (o no funciona)? - ¿Por qué la segunda promesa no presentó una excepción cuando no pasé una función?
¿Por qué
console.log("before 2 seconds (instantly)")
se ejecuta de inmediato (o no funciona)?
Los parámetros de una función se evalúan antes de llamar a la función. Cuando haces una alert(1+2)
esperas que 1+2
sea evaluado primero, y cuando haces una alert(console.log("..."))
también deberías esperar console.log("...")
para ser evaluado primero. No hay nada de especial en then
; es solo una función regular y sus argumentos son tratados de la misma manera que los argumentos de cualquier otra función.
¿Por qué la segunda promesa no presentó una excepción cuando no pasé una función?
Debido a que console.log
devuelve undefined
, y la especificación del lenguaje ( ECMAScript 2015 ) dice lo que debe suceder cuando llama then(undefined)
, y no está lanzando una excepción. Veamos lo que dice:
25.4.5.3.1 PerformPromiseThen (promesa, onFulfilled, onRejected, resultCapability)
La operación abstracta PerformPromiseThen realiza la operación "then" en la promesa utilizando onFulfilled y onRejected como sus acciones de liquidación. El resultado es la promesa de resultCapability .
- Afirmar: IsPromise ( promesa ) es verdad .
- Afirmar : resultCapability es un registro PromiseCapability.
- Si IsCallable ( onFulfilled ) es falso , entonces
- Deje que Fatiga sea
"Identity"
.- Si IsCallable ( onRejected ) es falso , entonces
- Let onRejected sea
"Thrower"
.- Deje que fulfillReaction sea la PromiseReaction {[[Capabilities]]: resultCapability , [[Handler]]: onFulfilled }.
- ...
Los puntos destacados aquí son (3) y (5). En (3), dado que onFulfilled undefined
está undefined
, IsCallable ( onFulfilled ) es falso y así onFulfilled se establece en "Identity"
. Luego, en (5), se crea una PromiseReaction con el [[Handler]] enFulfulled , que sabemos que es "Identity"
.
Esto es lo que dice la sección PromiseReaction Records sobre "Identity"
:
Si [[Handler]] es
"Identity"
, es equivalente a una función que simplemente devuelve su primer argumento.
Entonces ahí lo tienes. Llamar then(undefined)
es básicamente lo mismo que llamar then(a => a)
, por lo que no se obtiene un error.
¿Por qué es posible pasar un parámetro no funcional a Promise.then () sin causar un error?
Sí. Todos los argumentos no funcionales deben ignorarse. Vea abajo.
¿Por qué console.log ("antes de 2 segundos (al instante)") se ejecuta de inmediato (o no funciona)?
Porque en JS las llamadas a argumentos a funciones se evalúan instantáneamente (orden de aplicación).
¿Por qué la segunda promesa no presentó una excepción cuando no pasé una función?
Porque console.log
devuelve undefined
y .then()
sin argumentos es legal (porque ambos manejadores son opcionales). En su ejemplo, console.log()
devuelve indefinido, por lo que es como llamar a .then()
sin argumentos.
Pero incluso si se llama con algunos argumentos que no son funciones, aún así serían ignorados. Por ejemplo, incluso en este ejemplo, el ''ok'' aún llegaría a console.log
al final, lo que puede ser sorprendente:
Promise.resolve(''ok'')
.then()
.then(false)
.then(null)
.then(1)
.then(''x'')
.then([1, 2, 3])
.then({a: 1, b: 2})
.then(console.log);
Consulte la especificación Promises / A + , sección 2.2.1 que describe los argumentos del método .then()
:
2.2.1 Tanto onFulfilled como onRejected son argumentos opcionales:
- Si onFulfilled no es una función, debe ignorarse.
- Si onRejected no es una función, se debe ignorar.
El código
console.log("before 3 seconds (instantly)")
es una expresión , específicamente una expresión de llamada de función. Donde quiera que aparezca, significa lo mismo, incluida una apariencia como argumento del método .then()
de una Promesa. Como en cualquier otro lenguaje similar, una expresión utilizada en una llamada a función se evalúa antes de la llamada a la función, por lo que
.then(console.log("before 3 seconds (instantly)"))
da como resultado que se llame primero a la función .then()
luego se pasa el valor de retorno a .then()
. Es por eso que ves el mensaje en la consola de inmediato.
Pasar undefined
a .then()
está permitido, y como eso es lo que devuelve .then()
undefined
.then()
ningún error.
Si desea que console.log()
suceda cuando se cumpla la Promesa, debe envolverlo en una función:
.then(function() { console.log("after 3 seconds"); })