He leído varios artículos sobre este tema, pero todavía no me queda claro si hay una diferencia entre Promise.reject
vs. lanzar un error. Por ejemplo,
Usando Promise.reject
return asyncIsPermitted()
.then(function(result) {
if (result === true) {
return true;
}
else {
return Promise.reject(new PermissionDenied());
}
});
Usando tiro
return asyncIsPermitted()
.then(function(result) {
if (result === true) {
return true;
}
else {
throw new PermissionDenied();
}
});
Prefiero usar throw
simplemente porque es más corto, pero me preguntaba si hay alguna ventaja de uno sobre el otro.
javascript
promise
Naresh
fuente
fuente
.then()
controlador detecta la excepción lanzada y la convierte automáticamente en una promesa rechazada. Como he leído que las excepciones lanzadas no son particularmente rápidas de ejecutar, supongo que devolver la promesa rechazada podría ser un poco más rápido de ejecutar, pero tendrías que idear una prueba en varios navegadores modernos si eso fuera importante. Yo personalmente usothrow
porque me gusta la legibilidad.throw
es que no daría lugar a una promesa rechazada si se lanzara desde una devolución de llamada asincrónica, como un setTimeout. jsfiddle.net/m07van33 @Blondie su respuesta fue correcta.reject
de mi lista de parámetros.Respuestas:
No hay ninguna ventaja de usar uno frente al otro, pero hay un caso específico en el
throw
que no funcionará. Sin embargo, esos casos se pueden arreglar.Cada vez que esté dentro de una devolución de llamada de promesa, puede usarla
throw
. Sin embargo, si está en cualquier otra devolución de llamada asincrónica, debe usarlareject
.Por ejemplo, esto no activará la captura:
En cambio, te queda una promesa no resuelta y una excepción no alcanzada. Ese es un caso en el que desearía utilizarlo
reject
. Sin embargo, puede solucionar esto de dos maneras.fuente
throw error
, tampoco puede usar,return Promise.reject(err)
que es lo que el OP nos pidió que comparemos. Esta es básicamente la razón por la que no debe poner devoluciones de llamada asíncronas dentro de las promesas. Promete todo lo que es asíncrono y luego no tienes estas restricciones.Array#forEach
) y con ellas, lanzarlas dentro de ellas funcionaría.throw
que no funcionarán y, en cambio,Promise.reject
es una mejor opción. Sin embargo, los fragmentos no se ven afectados con ninguna de esas dos opciones y dan el mismo resultado independientemente de lo que elija. ¿Me estoy perdiendo de algo?reject
que se pasó a lanew Promise(fn)
devolución de llamada.return Promise.reject()
ythrow
. No menciona lareject
devolución de llamada dada en lanew Promise(function(resolve, reject))
construcción. Entonces, si bien sus dos fragmentos demuestran correctamente cuándo debe usar la devolución de llamada de resolución, la pregunta de OP no fue esa.Otro hecho importante es que
reject()
NO termina el flujo de control como lo hace unareturn
declaración. Por el contrariothrow
, termina el flujo de control.Ejemplo:
vs
fuente
return reject()
, para que la siguiente línea no se ejecute.return reject()
es simplemente una abreviatura de, porreject(); return
ejemplo, lo que desea es terminar el flujo. El valor de retorno del ejecutor (la función pasada anew Promise
) no se utiliza, por lo que es seguro.Sí, la mayor diferencia es que el rechazo es una función de devolución de llamada que se lleva a cabo después de que se rechaza la promesa, mientras que throw no se puede usar de forma asincrónica. Si opta por usar Rechazar, el código seguirá funcionando normalmente de forma asíncrona, mientras que tiro priorizará completar la función de resolución (esta función se ejecutará inmediatamente).
Un ejemplo que he visto que me ayudó a aclarar el problema fue que podía establecer una función de tiempo de espera con rechazo, por ejemplo:
Lo anterior no podría ser posible escribir con tiro.
En su pequeño ejemplo, la diferencia es indistinguible, pero cuando se trata de un concepto asincrónico más complicado, la diferencia entre los dos puede ser drástica.
fuente
TLDR: una función es difícil de usar cuando a veces devuelve una promesa y a veces arroja una excepción. Al escribir una función asíncrona, prefiera señalar la falla devolviendo una promesa rechazada
Su ejemplo particular ofusca algunas distinciones importantes entre ellos:
Debido a que está manejando errores dentro de una cadena de promesa, las excepciones lanzadas se convierten automáticamente en promesas rechazadas. Esto puede explicar por qué parecen ser intercambiables, no lo son.
Considere la siguiente situación:
Esto sería un antipatrón porque necesitaría admitir casos de error de sincronización y asíncrono. Podría parecerse a algo como:
No es bueno y aquí es exactamente donde
Promise.reject
(disponible en el ámbito global) viene al rescate y efectivamente se diferencia de sí mismothrow
. El refactor ahora se convierte en:Esto ahora le permite usar solo uno
catch()
para fallas en la red y la verificación de errores síncronos por falta de tokens:fuente
Promise.reject
othrow
cuándo desea devolver una promesa rechazada (una promesa que saltará a la siguiente.catch()
).checkCredentials(x).then(onFulfilled).catch(e) {}
y tener elcatch
control tanto del caso de rechazo como del caso de error arrojado?Un ejemplo para probar. Simplemente cambie isVersionThrow a false para usar el rechazo en lugar del lanzamiento.
fuente