Errores
Hablemos de errores.
Hay dos tipos de errores:
- errores esperados
- errores inesperados
- errores fuera de uno
Errores esperados
Los errores esperados son estados en los que sucede algo incorrecto, pero usted sabe que podría ocurrir, por lo que debe lidiar con eso.
Estas son cosas como la entrada del usuario o solicitudes del servidor. Usted sabe que el usuario puede cometer un error o que el servidor puede estar inactivo, por lo que debe escribir un código de verificación para asegurarse de que el programa solicite información nuevamente, o muestre un mensaje, o cualquier otro comportamiento apropiado.
Estos son recuperables cuando se manejan. Si se deja sin control, se convierten en errores inesperados.
Errores inesperados
Los errores inesperados (errores) son estados en los que sucede algo incorrecto porque el código es incorrecto. Sabes que eventualmente sucederán, pero no hay forma de saber dónde o cómo lidiar con ellos porque, por definición, son inesperados.
Estas son cosas como la sintaxis y los errores lógicos. Puede tener un error tipográfico en su código, puede haber llamado a una función con los parámetros incorrectos. Estos no suelen ser recuperables.
try..catch
Hablemos de eso try..catch.
En JavaScript, throwno se usa comúnmente. Si busca ejemplos en el código, serán pocos y distantes entre sí, y generalmente estructurados de acuerdo con las líneas de
function example(param) {
if (!Array.isArray(param) {
throw new TypeError('"param" should be an array!');
}
...
}
Debido a esto, los try..catchbloques tampoco son tan comunes para el flujo de control. Por lo general, es bastante fácil agregar algunas comprobaciones antes de llamar a los métodos para evitar los errores esperados.
Los entornos JavaScript también son bastante indulgentes, por lo que los errores inesperados a menudo también se dejan sin detectar.
try..catchno tiene que ser infrecuente Hay algunos casos de uso agradables, que son más comunes en lenguajes como Java y C #. Java y C # tienen la ventaja de las catchconstrucciones escritas , para que pueda diferenciar entre errores esperados e inesperados:
C # :
try
{
var example = DoSomething();
}
catch (ExpectedException e)
{
DoSomethingElse(e);
}
Este ejemplo permite que otras excepciones inesperadas fluyan y se manejen en otro lugar (como iniciar sesión y cerrar el programa).
En JavaScript, esta construcción se puede replicar a través de:
try {
let example = doSomething();
} catch (e) {
if (e instanceOf ExpectedError) {
DoSomethingElse(e);
} else {
throw e;
}
}
No es tan elegante, que es parte de la razón por la cual es poco común.
Las funciones
Hablemos de funciones.
Si utiliza el principio de responsabilidad única , cada clase y función debe cumplir un propósito singular.
Por ejemplo, authenticate()podría autenticar a un usuario.
Esto podría escribirse como:
const user = authenticate();
if (user == null) {
// keep doing stuff
} else {
// handle expected error
}
Alternativamente, podría escribirse como:
try {
const user = authenticate();
// keep doing stuff
} catch (e) {
if (e instanceOf AuthenticationError) {
// handle expected error
} else {
throw e;
}
}
Ambos son aceptables.
Promesas
Hablemos de promesas.
Las promesas son una forma asincrónica de try..catch. Llamando new Promiseo Promise.resolvecomienza su trycódigo. Llamando throwo Promise.rejectte envía al catchcódigo.
Promise.resolve(value) // try
.then(doSomething) // try
.then(doSomethingElse) // try
.catch(handleError) // catch
Si tiene una función asincrónica para autenticar a un usuario, puede escribirla como:
authenticate()
.then((user) => {
if (user == null) {
// keep doing stuff
} else {
// handle expected error
}
});
Alternativamente, podría escribirse como:
authenticate()
.then((user) => {
// keep doing stuff
})
.catch((e) => {
if (e instanceOf AuthenticationError) {
// handle expected error
} else {
throw e;
}
});
Ambos son aceptables.
Anidamiento
Hablemos de anidar.
try..catchpuede ser anidado Su authenticate()método puede tener internamente un try..catchbloque como:
try {
const credentials = requestCredentialsFromUser();
const user = getUserFromServer(credentials);
} catch (e) {
if (e instanceOf CredentialsError) {
// handle failure to request credentials
} else if (e instanceOf ServerError) {
// handle failure to get data from server
} else {
throw e; // no idea what happened
}
}
Del mismo modo, las promesas se pueden anidar. Su authenticate()método asíncrono podría usar promesas internamente:
requestCredentialsFromUser()
.then(getUserFromServer)
.catch((e) => {
if (e instanceOf CredentialsError) {
// handle failure to request credentials
} else if (e instanceOf ServerError) {
// handle failure to get data from server
} else {
throw e; // no idea what happened
}
});
Entonces, ¿cuál es la respuesta?
Ok, creo que es hora de que realmente responda la pregunta:
¿Se considera que una falla en la autenticación rechazaría una promesa?
La respuesta más simple que puedo dar es que debe rechazar una promesa en cualquier lugar donde de lo contrario desearía throwuna excepción si fuera un código síncrono.
Si su flujo de control es más simple al hacer algunas ifverificaciones en sus thendeclaraciones, no hay necesidad de rechazar una promesa.
Si su flujo de control es más simple al rechazar una promesa y luego verificar los tipos de errores en su código de manejo de errores, hágalo en su lugar.
rejecty no devolver falso, pero si espera que el valor sea aBool, entonces tuvo éxito y debe resolver con el Bool independientemente del valor. Las promesas son una especie de representación de los valores: almacenan el valor devuelto, por lo que solo si el valor no se puede obtener, usted debe hacerloreject. De lo contrario deberíasresolve.