javascript - w3school - Constructor de promesas con rechazo de llamada vs error de lanzamiento
tutorial promises (4)
¿Hay alguna diferencia entre usar el
reject
(enp2
) de la API dePromise
y lanzar un error (enp1
) usandothrow
?
Sí, no
cannot
usar
throw
asincrónicamente, mientras que el
reject
es una devolución de llamada.
Por ejemplo, un tiempo de espera:
new Promise(_, reject) {
setTimeout(reject, 1000);
});
¿Es exactamente lo mismo?
No, al menos no cuando otro código sigue su declaración.
throw
completa inmediatamente la función de resolución, mientras que llamar a
reject
continúa la ejecución normalmente, después de haber "marcado" la promesa como rechazada.
Además, los motores pueden proporcionar información de depuración de excepciones diferente si
throw
objetos de error.
Para su ejemplo específico, tiene razón en que
p1
y
p2
son indistinguibles del exterior.
En el siguiente código:
var p1 = new Promise(function (resolve, reject) {
throw ''test1'';
});
var p2 = new Promise(function (resolve, reject) {
reject(''test2'');
});
p1.catch(function (err) {
console.log(err); // test1
});
p2.catch(function (err) {
console.log(err); // test2
});
¿Hay alguna diferencia entre usar el
reject
(en
p2
) de la API de
Promise
y lanzar un error (en
p1
) usando
throw
?
¿Es exactamente lo mismo?
Si es lo mismo, ¿por qué necesitamos una devolución de llamada de
reject
?
No, no lo hay, los dos son completamente idénticos.
La única diferencia y por qué necesitamos
reject
es cuando necesita rechazar de forma asincrónica; por ejemplo, si está convirtiendo una API basada en devolución de llamada, es posible que deba señalar un error asincrónico.
var p = new Promise(function(resolve, reject){
someCallbackApi(function(err, data){
if(err) reject(err); // CAN''T THROW HERE, non promise context, async.
else resolve(data);
});
});
Sé que esto es un poco tarde, pero realmente no creo que ninguna de estas respuestas responda por completo a las preguntas que tuve cuando encontré esto. Aquí hay un ejemplo más completo para jugar.
var p1 = new Promise(function (resolve, reject) {
throw ''test 1.1''; //This actually happens
console.log(''test 1.1.1''); //This never happens
reject(''test 1.2''); //This never happens because throwing an error already rejected the promise
console.log(''test 1.3''); //This never happens
});
var p2 = new Promise(function (resolve, reject) {
reject(''test 2.1''); //This actually happens
console.log(''test 2.1.1''); //This happens BEFORE the Promise is rejected because reject() is a callback
throw ''test 2.2''; //This error is caught and ignored by the Promise
console.log(''test 2.3''); //This never happens
});
var p3 = new Promise(function (resolve, reject) {
setTimeout(function() { reject(''test 3.1'');}, 1000); //This never happens because throwing an error already rejected the promise
throw(''test 3.2''); //This actually happens
console.log(''test 3.3''); //This never happens
});
var p4 = new Promise(function (resolve, reject) {
throw(''test 4.1''); //This actually happens
setTimeout(function() { reject(''test 4.2'');}, 1000); //This never happens because throwing an error already rejected the promise
console.log(''test 4.3''); //This never happens
});
var p5 = new Promise(function (resolve, reject) {
setTimeout(function() { throw(''test 5.1'');}, 1000); //This throws an Uncaught Error Exception
reject(''test 5.2''); //This actually happens
console.log(''test 5.3''); //This happens BEFORE the Promise is rejected because reject() is a callback
});
var p6 = new Promise(function (resolve, reject) {
reject(''test 6.1''); //This actually happens
setTimeout(function() { throw(''test 6.2'');}, 1000); //This throws an Uncaught Error Exception
console.log(''test 6.3''); //This happens BEFORE the Promise is rejected because reject() is a callback
});
p1.then(function (resolve) {
console.log(resolve, "resolved")
}, function (reject) {
console.log(reject, "rejected")
}).catch(function (err) {
console.log(err, "caught"); // test1
});
p2.then(function (resolve) {
console.log(resolve, "resolved")
}, function (reject) {
console.log(reject, "rejected")
}).catch(function (err) {
console.log(err, "caught"); // test2
});
p3.then(function (resolve) {
console.log(resolve, "resolved")
}, function (reject) {
console.log(reject, "rejected")
}).catch(function (err) {
console.log(err, "caught"); // test3
});
p4.then(function (resolve) {
console.log(resolve, "resolved")
}, function (reject) {
console.log(reject, "rejected")
}).catch(function (err) {
console.log(err, "caught"); // test4
});
p5.then(function (resolve) {
console.log(resolve, "resolved")
}, function (reject) {
console.log(reject, "rejected")
}).catch(function (err) {
console.log(err, "caught"); // test5
});
p6.then(function (resolve) {
console.log(resolve, "resolved")
}, function (reject) {
console.log(reject, "rejected")
}).catch(function (err) {
console.log(err, "caught"); // test6
});
Una observación muy interesante es que si usa
throw
, será manejado primero por el controlador de
reject
y luego el controlador de
error
si no hay un controlador de rechazo en su lugar.
Con bloque de manejo de rechazos
var allowed = false;
var p1 = new Promise(
function(resolve, reject) {
if (allowed)
resolve(''Success'');
else
// reject(''Not allowed'');
throw new Error(''I threw an error'')
})
p1.then(function(fulfilled) {
console.log(''Inside resolve handler, resolved value: '' + fulfilled);
}, function(rejected) {
console.log(''Inside reject handler, rejected value: '' + rejected);
}).catch(function(error) {
console.log(''Inside error handler, error value: '' + error);
})
Sin bloque de manejo de rechazo
var allowed = false;
var p1 = new Promise(
function(resolve, reject) {
if (allowed)
resolve(''Success'');
else
// reject(''Not allowed'');
throw new Error(''I threw an error'')
})
p1.then(function(fulfilled) {
console.log(''Inside resolve handler, resolved value: '' + fulfilled);
}).catch(function(error) {
console.log(''Inside error handler, error value: '' + error);
})
Además, el bloque catch podrá detectar cualquier error arrojado dentro del controlador de
resolve
.
var allowed = true;
var p1 = new Promise(
function(resolve, reject) {
if (allowed)
resolve(''Success'');
else
// reject(''Not allowed'');
throw new Error(''I threw an error'')
})
p1.then(function(fulfilled) {
console.log(''Inside resolve handler, resolved value: '' + fulfilled);
throw new Error(''Error created inside resolve handler block'');
}).catch(function(error) {
console.log(''Inside error handler, error value: '' + error);
})
Parece que es mejor usar
throw
, a menos que no pueda si está ejecutando alguna tarea asincrónica, tendrá que pasar la devolución de llamada de
reject
a la función asincrónica.
Pero hay una solución, que es promisificar su función asíncrona.
Más en
https://.com/a/33446005