Cuál es la diferencia entre:
new Promise(function(res, rej) {
res("aaa");
})
.then(function(result) {
return "bbb";
})
.then(function(result) {
console.log(result);
});
y esto:
new Promise(function(res, rej) {
res("aaa");
})
.then(function(result) {
return Promise.resolve("bbb");
})
.then(function(result) {
console.log(result);
});
Pregunto ya que obtengo un comportamiento diferente Uso del servicio Angular y $ http con el encadenamiento .then (). Demasiado código, por lo tanto, primero el ejemplo anterior.
javascript
angularjs
promise
q
spirytus
fuente
fuente
Promise.resolve()
en el segundo ejemplo es innecesario.then
controlador, de hecho, es un aspecto clave de la especificación de promesas que puede hacer eso.then
s anidados arbitrariamente : el término 'otros idiomas' para esto es quethen
es amap
y aflatMap
.new Promise((res, rej) => { return fetch('//google.com').then(() => { return "haha"; }) }).then((result) => alert(result));
este código simplemente se bloqueará (no se resolverá para siempre). Pero si cambioreturn "haha";
a,return res("haha");
entonces funcionará y alertará a "jaja". ¿El fetch (). Then () ya envolvió "jaja" en una promesa resuelta?Respuestas:
La regla es, si la función que está en el
then
controlador devuelve un valor, la promesa se resuelve / rechaza con ese valor, y si la función devuelve una promesa, lo que sucede es que la siguientethen
cláusula será lathen
cláusula de la promesa que la función devolvió , por lo tanto, en este caso, el primer ejemplo cae a través de la secuencia normal de losthens
valores e imprime como se podría esperar, en el segundo ejemplo, el objeto de promesa que se devuelve cuando lo hacePromise.resolve("bbb")
es elthen
que se invoca al encadenar (para todos los efectos). La forma en que realmente funciona se describe a continuación con más detalle.Citando de las promesas / especificaciones A +:
La clave para notar aquí es esta línea:
fuente
then
controlador devuelve una promesa. +1 para la referencia de especificaciones.[[Resolve]]
se llama tanto enthen
valores como en valores, por lo que esencialmente envuelve un valor con la promesa, por lo quereturn "aaa"
es el mismoreturn Promise.resolve("aaa")
yreturn Promise.resolve("aaa")
es el mismoreturn Promise.resolve(Promise.resolve("aaa"))
, ya que la resolución es idempotente al llamarlo a un valor más que una vez tiene el mismo resultado."aaa"
yreturn Promise.resolve("aaa")
son intercambiables enthen
ables en cualquier caso?En términos simples, dentro de una
then
función de controlador:A) Cuando
x
es un valor (número, cadena, etc.):return x
es equivalente areturn Promise.resolve(x)
throw x
es equivalente areturn Promise.reject(x)
B) Cuándo
x
es una promesa que ya está liquidada (ya no está pendiente):return x
es equivalente areturn Promise.resolve(x)
, si la promesa ya se resolvió.return x
es equivalente areturn Promise.reject(x)
, si la promesa ya fue rechazada.C) Cuando
x
hay una promesa pendiente:return x
devolverá una Promesa pendiente y se evaluará en el siguientethen
.Lea más sobre este tema en los documentos Promise.prototype.then () .
fuente
Ambos ejemplos deberían comportarse más o menos igual.
Un valor devuelto dentro de un
then()
controlador se convierte en el valor de resolución de la promesa devuelta de esothen()
. Si el valor devuelto dentro del.then
es una promesa, la promesa devuelta porthen()
"adoptará el estado" de esa promesa y se resolverá / rechazará tal como lo hace la promesa devuelta.En su primer ejemplo, regresa
"bbb"
en el primerthen()
controlador, por lo que"bbb"
se pasa al siguientethen()
controlador.En su segundo ejemplo, devuelve una promesa que se resuelve de inmediato con el valor
"bbb"
, por lo que"bbb"
se pasa al siguientethen()
controlador. (ElPromise.resolve()
aquí es extraño).El resultado es el mismo.
Si puede mostrarnos un ejemplo que en realidad exhibe un comportamiento diferente, podemos decirle por qué sucede eso.
fuente
Promise.resolve();
vsreturn;
?undefined
lugar de"bbb"
.Ya tienes una buena respuesta formal. Pensé que debería agregar uno corto.
Las siguientes cosas son idénticas a las promesas / promesas A + :
Promise.resolve
(en su caso angular, eso es$q.when
)new $q
.then
devolución de llamada.Por lo tanto, los siguientes son idénticos para una promesa o un valor simple X:
Y no es sorprendente, la especificación de promesas se basa en el Procedimiento de resolución de promesas que permite una fácil interoperación entre bibliotecas (como $ q y promesas nativas) y hace que su vida sea más fácil en general. Cada vez que se produce una resolución prometedora, se produce una resolución que crea coherencia general.
fuente
Promise.resolve().then(function(){ return x; });
? Encontré un recorte haciendo algo similar (llamó una función dentro delthen
bloque). Pensé que era más o menos como hacer un tiempo de espera, pero es un poco más rápido. jsben.ch/HIfDowith
bloque sobre un objeto o proxy con unx
descriptor de acceso de propiedad que arroja una excepción. En ese caso, Promise.resolve (x) causaría un error arrojado peroPromise.resolve().then(function(){ return x; });
sería una promesa rechazada ya que el error es arrojado en athen
).if (validator) { Promise.resolve().then(() => { this._cdRef.markForCheck(); }); }
. Aquí la promesa no está asignada, entonces, ¿cuál es el punto? Un tiempo de espera tendría (más o menos) el mismo efecto, ¿o no?La única diferencia es que estás creando una promesa innecesaria cuando lo haces
return Promise.resolve("bbb")
. Devolver una promesa de unonFulfilled()
controlador inicia la resolución de la promesa . Así es como funciona el encadenamiento de promesas .fuente