Cómo buscar errores en el front-end: 4 etapas principales


En este artículo consideraré el problema de identificar y manejar los errores que ocurren en la interfaz (navegador o vista web).

En la interfaz, el código JS se ejecuta en el navegador. JavaScript no es un lenguaje compilado, por lo que siempre existe la posibilidad de un error de rendimiento al usar el programa directamente. Un error de ejecución bloquea el código ubicado después de la ubicación del error, y los usuarios del programa corren el riesgo de quedarse con una pantalla de aplicación no funcional que solo se puede recargar o cerrar. Pero existen métodos para detectar errores y su acompañamiento seguro, para evitar tales situaciones.

1. Herramientas de JavaScript


Probar / atrapar bloques


Las funciones que pueden fallar pueden estar envueltas en bloques try / catch. Primero, el programa intenta ejecutar el código en el bloque try. Si por alguna razón la ejecución del código se rompe, el programa entra en el bloque catch, donde hay tres parámetros disponibles:

  • nombre: nombre estandarizado del error;
  • mensaje: mensaje sobre los detalles del error;
  • stack: la pila de llamadas actual en la que se produjo el error.

Es decir:

try {

   callFunc();

} catch (e) {

   console.log(e.name) // ReferenceError

   console.log(e.message) // callFunc is not defined

   console.log(e.stack) // ReferenceError: callFunc is not defined at window.onload

}

Para el desarrollador, lo principal es que el programa podrá continuar la ejecución después del bloque catch. Por lo tanto, la interacción del usuario no se interrumpirá.

Usando el bloque try / catch, también puede causar sus propios errores, por ejemplo, al verificar datos:

const user = {

  name : «Mike»

};

try {

   if (!user.age) throw new SyntaxError(«User age is absent!»);

} catch (e) {

   console.log(e.name) // SyntaxError

   console.log(e.message) // User age is absent!

   console.log(e.stack) // SyntaxError: User age is absent! at window.onload

}

Finalmente, puede extender esta declaración con un bloque más, finalmente, que siempre se ejecuta: tanto en el caso en que no hubo error en el intento, como en el caso de que el control pasara al bloque catch:

try {

   callFunc();

} catch (e) {

   console.log(e)

} finally {

   ...

}

A veces usan la declaración try / finally (sin captura) para que pueda continuar usando el código sin manejar errores específicos.

Evento Window.onerror


A menudo es útil saber que la secuencia de comandos en la página se ha roto, incluso si el programa se ha roto y la sesión del usuario ha finalizado sin éxito. Por lo general, esta información se utiliza en sistemas de registro de errores.

El objeto de ventana global tiene un evento onerror (úselo con cuidado: ¡la implementación puede diferir en diferentes navegadores! ):

window.onerror = function(message, url, line, col, error) {

   console.log(`${message}\n  ${line}:${col}  ${url}`);

};

Si coloca este código al comienzo de la secuencia de comandos o lo carga en una secuencia de comandos separada, en primer lugar, para cualquier error debajo del desarrollador estará disponible información detallada al respecto.

Sin embargo, la información completa solo está disponible para los scripts que se han descargado del mismo dominio. Si el script roto se carga desde otro dominio, window.onerror funcionará, pero no habrá detalles del error.

Componentes del marco


Algunos marcos JS ( React , Vue) ofrecen sus propias soluciones de manejo de errores. Por ejemplo, React podrá dibujar un diseño especial en la ubicación del bloque en el que ocurrió el error:

class ErrorBoundary extends React.Component {

   constructor(props) {

       super(props);

       this.state = { hasError: false };

   }

   static getDerivedStateFromError(error) {

       //    ,      UI.

       return { hasError: true };

   }

   componentDidCatch(error, errorInfo) {

       //           

       logErrorToMyService(error, errorInfo);

   }

   render() {

       if (this.state.hasError) {

           //    UI  

           return <h1>-   .</h1>;

       }

       return this.props.children;

   }

}

<ErrorBoundary>

   <MyWidget />

</ErrorBoundary>

De hecho, el componente React está envuelto en un componente especial que maneja los errores. Esto es similar a las funciones de ajuste con una construcción try / catch.

2. Herramientas de montaje de proyectos.


Los scripts JS modernos generalmente se hacen transpilados. Es decir, el desarrollo se lleva a cabo utilizando los últimos estándares de ES. Y luego, el código del desarrollador que usa el creador de proyectos (como Webpack) se convierte en código que se garantizará que funcione en el número seleccionado de navegadores.

En la etapa de compilación, el código se verifica para la sintaxis correcta. Un corchete abierto o una designación incorrecta de un campo de clase provocará inmediatamente un error durante el ensamblaje, y el paquete simplemente no se ensamblará. El desarrollador tendrá que corregir inmediatamente dichos errores para continuar trabajando.

Además, el recopilador puede sugerir que algunas piezas de código no se usen al ejecutar el programa. Quizás esto incite al desarrollador a pensar en un estudio más profundo del código, que puede afectar indirectamente la identificación de nuevos errores.

3. Prueba


Otra forma de evitar errores en el código es probarlo. Hay herramientas en la interfaz para el uso efectivo de las pruebas unitarias. Por lo general, se utilizan marcos como Jest, Karma, Mocha, Jasmine. Junto con los marcos de prueba, a menudo usan extensiones como Enzyme, React Testing Library, Sinon y otras, que permiten pruebas enriquecedoras con la ayuda de mocha, funciones de espionaje y otras herramientas.

Al buscar errores, las pruebas son principalmente útiles para cargar una variedad de datos que pueden conducir a errores de ejecución. Entonces, el siguiente código pasará la validación de sintaxis y funcionará como se espera:

const func = (data) => {

   return JSON.parse(data)

}

func('{«a»:1}')

Sin embargo, se romperá si le da el valor incorrecto:

func() // Uncaught SyntaxError: Unexpected token u in JSON at position 0.


Este código también pasa la validación durante el ensamblaje:

const obj = {

   outer : {

       last : 9

   }

}

if (obj.outer.inner.last) {

   console.log(«SUCCESS»)

}

Sin embargo, también se romperá durante la ejecución. Después de la prueba, el desarrollador probablemente hará verificaciones adicionales:

if (obj.outer?.inner?.last) {

   console.log(«SUCCESS»)

}

A menudo, tales errores ocurren cuando se reciben datos del servidor (por ejemplo, con una solicitud AJAX) con su posterior análisis. Probar el código le permite identificar y eliminar de antemano los casos en que el código puede romperse durante la ejecución en el navegador del cliente.

4. Registro


Supongamos que hemos tomado todas las medidas posibles para evitar errores durante el desarrollo y el ensamblaje del proyecto. Sin embargo, los errores aún pueden infiltrarse en el código productivo. Necesitamos conocer de alguna manera su presencia y tomar medidas correctivas inmediatas. Pedir a los usuarios que abran una consola del navegador y que tomen capturas de pantalla no es la mejor opción. Por lo tanto, es bueno conectar el registro de errores al proyecto.

El significado es simple: para cada evento window.onerror o cada transición de ejecución de código al bloque catch, se realiza una simple solicitud AJAX a una dirección de servidor especialmente asignada, en cuyo cuerpo se coloca la información sobre el error. A continuación, necesitará una herramienta que notificará rápidamente al soporte técnico y a los desarrolladores sobre la presencia de nuevos errores y le permitirá trabajar eficazmente con ellos. La más popular de estas herramientas frontend es Sentry.

El sistema de registro Sentry le permite recopilar, agrupar y presentar errores en tiempo real. Hay ensamblajes para diferentes idiomas, incluido JavaScript. El proyecto proporciona acceso pago con funciones avanzadas para empresas, sin embargo, puede probar sus funciones principales en una cuenta de prueba gratuita.

Sentry se puede conectar directamente en el archivo HTML y en componentes ejecutados en uno de los marcos populares: React, Vue, Angular, Ember y otros.

Para conectar las capacidades de registro directamente en el navegador en la sección, cargue el script:

<script

   src=«https://browser.sentry-cdn.com/5.13.0/bundle.min.js»

   integrity=«sha384-ePH2Cp6F+/PJbfhDWeQuXujAbpil3zowccx6grtsxOals4qYqJzCjeIa7W2UqunJ»

   crossorigin="anonymous"></script>


A continuación, en el código JS, inicializamos:

Sentry.init({

   dsn: 'https://<your account key here>@sentry.io/<your project id here>'

});

Todas. Si se produce un error en el código debajo de esta línea, Sentry lo registrará. Los registros se registrarán incluso cuando se produjo el error debido a la falla de los scripts de otros dominios:



Sentry tiene amplias oportunidades para analizar una serie de mensajes de error y configurar notificaciones. También es posible agrupar registros de errores por las versiones de su producto:

Sentry.init({

   dsn: 'https://<your account key here>@sentry.io/<your project id here>',

   release: '2020.03.06.1'

});

Con Sentry, las estadísticas se pueden usar para transferir el contexto de un error, por ejemplo, información del cliente, huella digital, nivel de error (fatal, error, advertencia, información, depuración) y etiqueta.

Es posible registrar eventos de usuario en estadísticas. Por ejemplo, puede configurar el seguimiento para cambiar el tamaño de la ventana del navegador o realizar una solicitud AJAX. Sentry también tiene su propio widget con una ventana de comentarios, que se puede mostrar al usuario en caso de error. Esto proporcionará información adicional para investigar las circunstancias del error.

Para implementar Sentry junto con los marcos, simplemente instale el paquete y conéctese:

# Using yarn

yarn add @sentry/browser

# Using npm

npm install @sentry/browser


Hacemos la inicialización en el script principal del proyecto (para React y Angular):

import * as Sentry from «@sentry/browser»;

Sentry.init({ dsn: 'https://<your account key here>@sentry.io/<your project id here>' });


Para Vue y Ember, pasamos otra línea de configuración requerida:

# Vue

Sentry.init({

   dsn: '<your account key here>@sentry.io/<your project id here>',

   integrations: [new Integrations.Vue({Vue, attachProps: true})],

});

# Ember

Sentry.init({

   dsn: '<your account key here>@sentry.io/<your project id here>',

   integrations: [new Integrations.Ember()]

});

El paquete de integraciones se instala por separado:

# Using yarn

yarn add @sentry/integrations

# Using npm

npm install @sentry/integrations

Para evitar conflictos y la duplicación de información al conectar varios scripts en un proyecto, Sentry le permite crear un cliente separado para cada inicialización de registro:

import { BrowserClient } from «@sentry/browser»;

const client = new BrowserClient({

   dsn: '<your account key here>@sentry.io/<your project id here>',

});

client.captureException(new Error('example'));

El sitio web del proyecto tiene documentación detallada con ejemplos de uso: https://docs.sentry.io .

Este artículo fue preparado con el soporte de la plataforma en la nube Mail.ru Cloud Solutions .

Qué más leer sobre el tema:

  1. Componentes reaccionables reaccionables: cómo dejar de escribir lo mismo .
  2. Cómo evitar errores al desarrollar en React .
  3. - .

All Articles