¿Cuáles son las mejores prácticas para el manejo de errores de JavaScript?

137

Estoy buscando para empezar a hacer mi JavaScript un poco más a prueba de errores, y yo estoy encontrando un montón de documentación sobre el uso de try, catch, finally, y throw, pero no voy a encontrar un montón de consejos de expertos sobre cuándo y dónde tirar errores.

  • ¿Debería cada pieza de código estar envuelta en un try / catch?
  • ¿Hay más consejos como este en qué punto se deben detectar los errores?
  • ¿Existen desventajas para generar errores en lugar de que el código falle silenciosamente en la producción?
  • Esto se ha tocado en SO en cuanto a implementaciones, pero ¿los errores JS de registro del servidor son una estrategia efectiva?
  • ¿Algo más que deba saber sobre los errores de captura en mi aplicación?

También estoy completamente listo para escuchar libros que tienen grandes capítulos o explicaciones detalladas sobre el manejo de errores. JavaScript elocuente toca el asunto, pero no es muy prescriptivo ni es obstinado sobre el tema.

¡Gracias por cualquier consejo que puedas dar!

Joshua Cody
fuente
Seguramente depende de cuán espectacularmente falle si algo sale mal y el volumen de posibles mensajes de error. No desea fallar porque su directorio de registro de errores está lleno ahora, ¿verdad? - ¿Has mirado aquí? stackoverflow.com/search?q=error+logging+javascript
mplungjan
@mplungjan: analicé las respuestas allí, pero no parecía mucho canónico, y las búsquedas de prácticas de excepción / manejo de errores de Javascript no resultaron nada, así que pensé que podría ser útil tratar de solicitar algunos pensamientos condensados, tanto para mi propio entendimiento y futuros buscadores. ¿Quizás este es un tema en el que la prescripción de las mejores prácticas no es tan posible, pero cada situación es altamente única?
Joshua Cody
1
"¿Se debe envolver cada fragmento de código en un intento / captura? Por supuesto no. Hay un montón de código que sabe que siempre funcionará (suponiendo que lo pruebe, por supuesto, pero el objetivo de try / catch no es detectar ni pasar por alto los errores de codificación). Solo ajuste el código que podría fallar algunas veces debido a algo fuera de su control, generalmente cosas como el acceso a los recursos, etc. Nota: algunas cosas que pueden fallar tienen un manejo de errores incorporado, por ejemplo, no me molestaría en codificar Ajax desde cero cuando Hay muchas bibliotecas que lo hacen que manejan problemas entre navegadores y le permiten especificar una función de controlador de errores.
nnnnnn
1
Esta es una buena pregunta Josh, +1. Hay muchos consejos sintácticos, pero como tú dices, esa es la parte fácil. Se menciona en la respuesta de esta pregunta ( stackoverflow.com/questions/2825427/… ) donde se explica que las excepciones no se usan tan comúnmente en JS y se dan razones.
whitneyland

Respuestas:

63

Se puede encontrar un conjunto de diapositivas inmensamente interesante en el Manejo de errores de JavaScript de empresa en http://www.devhands.com/2008/10/javascript-error-handling-and-general-best-practices/

En resumen, resume:

  1. Suponga que su código fallará
  2. Registrar errores en el servidor
  3. Usted, no el navegador, maneja errores
  4. Identificar dónde pueden ocurrir errores
  5. Lanza tus propios errores
  6. Distinguir errores fatales versus errores no fatales
  7. Proporcionar un modo de depuración

Las diapositivas entran en muchos más detalles y probablemente te darán alguna dirección.

ACTUALIZAR

La presentación mencionada anteriormente se puede encontrar aquí: http://www.slideshare.net/nzakas/enterprise-javascript-error-handling-presentation

cdmdotnet
fuente
24
El enlace devhands está roto.
Ryan Gates
77
Para aquellos que leyeron esto en 2017, les diría que no obtendrán mucho valor de las diapositivas: este resumen les brinda el 90% de la información. Todavía es información valiosa. ¡Salud!
Philippe Hebert
29

Nicholas Zakas de Yahoo! Fame hizo una charla sobre Enterprise Error Handling ( diapositivas ) en Ajax Experience 2008, en la que propuso algo como esto:

function log(sev,msg) {
    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

// usage
log(1, "Something bad happened.")

// Auto-log uncaught JS errors
window.onerror = function(msg, url, line) {
    log(1, msg);
    return true;
}

Un año después, Nicholas Zakas publicó una actualización en su blog que incluía un patrón inteligente para inyectar automáticamente el código de manejo de errores en su entorno de producción (utilizando programación orientada a aspectos).

Cuando comience a registrar las llamadas de window.error, notará dos cosas:

  1. Si su sitio es bastante complejo, registrará muchos errores
  2. Verás un montón de mensajes inútiles de "window.error en undefined: 0"

Reducir el torrente de entradas de registro es tan simple como probar la gravedad y / o un número aleatorio antes de iniciar sesión en el servidor:

function log(sev,msg) {
    if (Math.random() > 0.1) return; // only log some errors

    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

El manejo de los inútiles errores "window.error en undefined: 0" depende de la arquitectura de su sitio, pero puede intentar identificar todas las llamadas de Ajax y lanzar una excepción cuando algo falla (posiblemente devolviendo un seguimiento de pila usando stacktrace.js ).

Jens Roland
fuente
67
Sé que esta es una vieja pregunta, pero sugerir ignorar al azar algunos errores es una de las peores ideas que he escuchado.
jbabey 01 de
26
@jbabey: para un sitio pequeño tiene razón, pero si está ejecutando un sitio grande con 100,000 o millones de usuarios, realmente no necesita inundar sus servidores (o Internet) con solicitudes de registro redundantes. En un sistema lo suficientemente grande, cada error real ocurrirá decenas de miles de veces al día, por lo que esta forma de limitación funciona bien. La idea se implementa realmente en Facebook.
Jens Roland
1
Los errores de registro mientras está en modo de depuración probablemente sean tan importantes como limitar los informes de errores de producción, por lo que uno puede notar que se necesita una solución para administrar ese valor que limita el umbral de registro.
frattaro
2
@NickBull Realicé ingeniería inversa de un montón de módulos JavaScript de Facebook en 2011-2012; Ahí es donde lo encontré.
Jens Roland
1
@NickBull acaba de revisar mis viejos archivos, todavía tenía estos. Encontré este truco en el módulo del gestor de arranque de Facebook: if (global.logJSError) if (Math.random() < .01) logJSError('bootloader', {(es cierto que el código no limita todos los errores, solo una clase específica de errores de tiempo de espera)
Jens Roland
7

IHMO, debe usar el manejo de errores en javascript como lo hace en varios otros idiomas (AFAIK: Python, Java).

Para una mejor legibilidad (y probablemente un mejor rendimiento, aunque no estoy seguro de que tenga un gran impacto), debe usar el bloque try / catch principalmente en los siguientes casos:

  • La parte del código que desea ajustar es una parte clave de todo el algoritmo . Si falla, podría:

    • crear errores en la siguiente parte de los códigos (por ejemplo, porque falta una var ...)
    • hacer que la página no se vea como se esperaba (impacto en el contenido o css)
    • hacer que los resultados parezcan extraños para el usuario (impacto en el comportamiento del código)
  • Sabes que el código que estás escribiendo no es compatible con todos los navegadores

  • Planeaste que el código podría fallar (porque no hay otra manera de verificar que debería funcionar si ... entonces ... bloquea)
  • Y también cuando quieres depurar sin molestar al usuario final

Eventualmente, los expertos en JavaScript pueden tener otros elementos para dar.

mis 2 centavos a la caja,

Saludos,

Max

JMax
fuente
1
"La parte del código que desea ajustar es una parte clave de todo el algoritmo", puede depender de cómo desee manejar la falla. Si sabe que no hay forma de continuar con el algoritmo en caso de falla, podría ser mejor envolver todo en un try / catch porque si su try / catch está (por ejemplo) enterrado dentro de bucles anidados, será más un golpe de rendimiento . Por otro lado, si puede tomar alguna medida de excepción y continuar con el algoritmo, necesitará una configuración de prueba / captura más precisa.
nnnnnn
5

Además de las otras respuestas: una cosa importante es utilizar los datos de contexto disponibles en los objetos de error de JavaScript y en los window.onerrorparámetros de la función.

Cosas como el stacktrace (errorObject.stack), el nombre del archivo, el número de línea y el número de columna. Tenga en cuenta que cada navegador tiene algunas diferencias ... así que haga su mejor esfuerzo para obtener buenos errores.

Incluso puede haber problemas con el objeto de la consola en sí . Utilizo una función personalizada window.onerror inspirada en esta y una función especial para rastrear cualquier objeto de error estándar inspirado en este código .

Otro buen punto es incluir la versión de su aplicación web en algún lugar cercano al stacktrace (para copiar y pegar de manera rápida y segura). También puede mostrar errores de forma más agresiva (alerta ...) en modo de desarrollo ya que los desarrolladores no supervisarán constantemente la consola del navegador y es posible que no vean algunos de los problemas.

También use evitar el uso throw 'My message', use throw new Error('My message'), incluso puede tener errores personalizados, lea este artículo .

Siempre agregue algo de contexto a los errores (la versión, la identificación del objeto, algún mensaje personalizado, ...) y también asegúrese de hacer una distinción entre errores externos (algunos datos externos o circunstancias hicieron que su sistema fallara) y errores internos / aserciones (su propio sistema está en mal estado), lea sobre ' Diseño por contrato '.

Aquí hay una guía .

También piense en usar el manejo general de errores como interceptores en sus bibliotecas y marcos:

Christophe Roussy
fuente