Digamos que tengo esta función de autenticación que devuelve una promesa. La promesa luego se resuelve con el resultado. Falso y verdadero son los resultados esperados, según lo veo, y los rechazos solo deberían ocurrir en un caso de error. O, ¿una falla en la autenticación se considera algo por lo que rechazaría una promesa?
                    
                        javascript
                                
                    
                    
                        Mathieu Bertin
fuente
                
                fuente

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.falseo una excepción?thencuando el servidor responde, incluso si se devuelve un código de error, y debe verificar elresponse.ok. Elcatchcontrolador solo se activa para errores inesperados .Respuestas:
¡Buena pregunta! No hay una respuesta difícil. Depende de lo que considere excepcional en ese punto específico del flujo .
Rechazar a
Promisees lo mismo que plantear una excepción. No todos los resultados no deseados son excepcionales , el resultado de errores . Podría argumentar su caso en ambos sentidos:Falló la autenticación debe
rejectalPromise, debido a que la persona que llama está a la espera de unUserobjeto a cambio, y cualquier otra cosa es una excepción a este flujo.Falló la autenticación debe
resolvealPromise, aunque ennull, ya que proporciona las credenciales incorrectas no es realmente un excepcional caso, y la persona que llama debe no espera que el flujo de siempre resulta en unUser.Tenga en cuenta que estoy mirando el problema desde el lado de la persona que llama . En el flujo de información, ¿la persona que llama espera que sus acciones resulten en un
User(y cualquier otra cosa es un error), o tiene sentido que esta persona en particular maneje otros resultados?En un sistema de varias capas, la respuesta puede cambiar a medida que los datos fluyen a través de las capas. Por ejemplo:
nullusuario.Este ejemplo de 4 puntos es obviamente complicado, pero ilustra 2 puntos:
Así que de nuevo, no hay respuesta difícil. ¡Hora de pensar y diseñar!
fuente
Por lo tanto, las promesas tienen una buena propiedad que aportan JS de lenguajes funcionales, que es que implementan este
Eitherconstructor de tipos que une dos otros tipos, elLefttipo y elRighttipo, al forzar a la lógica a tomar una rama u otra rama.Ahora se está dando cuenta de que el tipo en el lado izquierdo es ambiguo para las promesas; puedes rechazar con cualquier cosa. Esto es cierto porque JS está tipado débilmente, pero debes ser cauteloso si estás programando a la defensiva.
La razón es que JS tomará
throwdeclaraciones del código de manejo de promesas y lo agrupará en elLeftlado de eso también. Técnicamente en JS puedesthrowtodo, incluso verdadero / falso o una cadena o un número: pero el código JavaScript también arroja cosas sinthrow(cuando haces cosas como intentar acceder a propiedades en nulos) y hay una API establecida para esto (elErrorobjeto) . Entonces, cuando empiezas a atrapar, generalmente es bueno poder asumir que esos errores sonErrorobjetos. Y dadorejectque la promesa se aglomerará en cualquier error de cualquiera de los errores anteriores, generalmente solo deseathrowotros errores, para que sucatchdeclaración tenga una lógica simple y consistente.Por lo tanto, aunque puede poner un if-conditional en su
catchy buscar errores falsos, en cuyo caso el caso de la verdad es trivial,probablemente preferirá la estructura lógica, al menos para lo que sale inmediatamente del autenticador, de un booleano más simple:
De hecho, el siguiente nivel de lógica de autenticación es probablemente devolver algún tipo de
Userobjeto que contenga al usuario autenticado, de modo que esto se convierta en:y esto es más o menos lo que esperaría: regresar
nullen el caso de que el usuario no esté definido; de lo contrario, regresar{user_id: <number>, permission_to_launch_missiles: <boolean>}. Esperaría que el caso general de no iniciar sesión sea rescatable, por ejemplo, si estamos en algún tipo de modo "demostración a nuevos clientes", y no debería mezclarse con errores donde accidentalmente llaméobject.doStuff()cuandoobject.doStuffestabaundefined.Ahora con eso dicho, lo que es posible que desee hacer es definir una
NotLoggedInoPermissionErrorexcepción que se deriva deError. Luego, en las cosas que realmente lo necesitan, desea escribir:fuente
Errores
Hablemos de errores.
Hay dos tipos de errores:
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..catchHablemos 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 deDebido 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.
C # :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 lascatchconstrucciones escritas , para que pueda diferenciar entre errores esperados e inesperados: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:
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:
Alternativamente, podría escribirse como:
Ambos son aceptables.
Promesas
Hablemos de promesas.
Las promesas son una forma asincrónica de
try..catch. Llamandonew PromiseoPromise.resolvecomienza sutrycódigo. LlamandothrowoPromise.rejectte envía alcatchcódigo.Si tiene una función asincrónica para autenticar a un usuario, puede escribirla como:
Alternativamente, podría escribirse como:
Ambos son aceptables.
Anidamiento
Hablemos de anidar.
try..catchpuede ser anidado Suauthenticate()método puede tener internamente untry..catchbloque como:Del mismo modo, las promesas se pueden anidar. Su
authenticate()método asíncrono podría usar promesas internamente:Entonces, ¿cuál es la respuesta?
Ok, creo que es hora de que realmente responda la pregunta:
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 susthendeclaraciones, 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.
fuente
He usado la rama "rechazar" de una Promesa para representar la acción "cancelar" de los cuadros de diálogo de jQuery UI. Parecía más natural que usar la rama "resolver", sobre todo porque a menudo hay múltiples opciones de "cerrar" en un cuadro de diálogo.
fuente
Manejar una promesa es más o menos como una condición de "si". Depende de usted si desea "resolver" o "rechazar" si la autenticación falla.
fuente
try..catch, noif.try...catchy simplemente decir que si pudo completar y obtener un resultado, debe resolver independientemente del valor recibido, de lo contrario, ¿debe rechazar?try { if (!doSomething()) throw whatever; doSomethingElse() } catch { ... }está perfectamente bien, pero la construcción quePromiserepresenta a es latry..catchparte, no laifparte.doSomething()falla, arrojará, pero si no podría contener el valor que necesita (loifanterior es un poco confuso ya que no es parte de su idea aquí :)). Solo debe rechazar si hay una razón para lanzar (en la analogía), por lo tanto, si la prueba falló. Si la prueba tuvo éxito, siempre debe resolver, independientemente de si su valor es positivo, ¿verdad?