parse nodejs node commands javascript node.js exception-handling expect.js

javascript - nodejs - parse node js



Volver a lanzar la excepción en NodeJS y no perder el seguimiento de pila (3)

No tengo conocimiento de un método nativo como Java y aún no he encontrado una solución elegante para envolver errores.

El problema con la creación de un new Error es que puede perder los metadatos que se adjuntaron al Error original que se lanzó, la pila y el tipo son generalmente lo que queda atrás.

Realizar modificaciones al error existente es más rápido, pero aún es posible modificar los datos del error que ya no existe. También se siente mal estar hurgando en un error que se creó en otro lugar.

Crear un nuevo error y una nueva pila

La propiedad .stack de un nuevo Error se puede modificar para que diga lo que le gusta antes de lanzarlo. Reemplazar una propiedad de la stack errores por completo puede ser realmente confuso para la depuración.

Cuando el error original y el controlador de errores se encuentran en ubicaciones o archivos separados, es posible que pueda rastrear el origen del error original pero no rastrear el controlador en el que realmente se detectó el error. Para evitar esto, es bueno mantener algunas referencias a ambos errores en la stack . También es útil tener acceso al error original completo si hay metadatos adicionales almacenados en él.

Aquí hay un ejemplo de cómo capturar un error, envolverlo en un nuevo error, pero agregar la stack original y almacenar el error :

try { throw new Error(''First one'') } catch (error) { let e = new Error(`Rethrowing the "${error.message}" error`) e.original = error e.stack = e.stack.split(''/n'').slice(0,2).join(''/n'') + ''/n'' + error.stack throw e }

Que lanza

/so/42754270/test.js:9 throw e ^ Error: Rethrowing the "First one" error at test (/so/42754270/test.js:5:13) Error: First one at test (/so/42754270/test.js:3:11) at Object.<anonymous> (/so/42754270/test.js:13:1) at Module._compile (module.js:570:32) at Object.Module._extensions..js (module.js:579:10) at Module.load (module.js:487:32) at tryModuleLoad (module.js:446:12) at Function.Module._load (module.js:438:3) at Module.runMain (module.js:604:10) at run (bootstrap_node.js:394:7) at startup (bootstrap_node.js:149:9)

Así que hemos creado un nuevo Error genérico. Desafortunadamente, el tipo del error original se oculta de la salida, pero el error se ha adjuntado como .original para que aún pueda accederse. La nueva stack se ha eliminado en gran parte, excepto la línea de generación que es importante, y la stack errores original se adjuntó.

Cualquier herramienta que intente analizar los seguimientos de la pila podría no funcionar con este cambio o, en el mejor de los casos, detectan dos errores.

Clases de error ES2015

Haciendo esto en una clase de error reutilizable ES2015 + ...

// Standard error extender from @deployable/errors class ExtendedError extends Error { constructor(message){ super(message) this.name = this.constructor.name this.message = message if (typeof Error.captureStackTrace === ''function''){ Error.captureStackTrace(this, this.constructor) } else { this.stack = (new Error(message)).stack } } } class RethrownError extends ExtendedError { constructor(message, error){ super(message) if (!error) throw new Error(''RethrownError requires a message and error'') this.original = error this.new_stack = this.stack let message_lines = (this.message.match(//n/g)||[]).length + 1 this.stack = this.stack.split(''/n'').slice(0, message_lines+1).join(''/n'') + ''/n'' + error.stack } } throw new RethrownError(`Oh no a "${error.message}" error`, error)

Resultados en

/so/42754270/test2.js:31 throw new RethrownError(`Oh no a "${error.message}"" error`, error) ^ RethrownError: Oh no a "First one" error at test (/so/42754270/test2.js:31:11) Error: First one at test (/so/42754270/test2.js:29:11) at Object.<anonymous> (/so/42754270/test2.js:35:1) at Module._compile (module.js:570:32) at Object.Module._extensions..js (module.js:579:10) at Module.load (module.js:487:32) at tryModuleLoad (module.js:446:12) at Function.Module._load (module.js:438:3) at Module.runMain (module.js:604:10) at run (bootstrap_node.js:394:7) at startup (bootstrap_node.js:149:9)

Entonces sabrá que siempre que vea un RethrownError el error original seguirá estando disponible en .original .

Este método no es perfecto, pero significa que puedo volver a escribir los errores conocidos de los módulos subyacentes en tipos genéricos que se manejan con mayor facilidad, generalmente con bluebirds filtrados .catch(TypeError, handler)

Mismo error con una pila modificada

Algunas veces tendrá que mantener el error original principalmente como está.

En este caso, simplemente puede agregar / insertar la nueva información en la pila existente.

file = ''/home/jim/plumbers'' try { JSON.parse(''k'') } catch (e) { let message = `JSON parse error in ${file}` let stack = new Error(message).stack e.stack = e.stack + ''/nFrom previous '' + stack.split(''/n'').slice(0,2).join(''/n'') + ''/n'' throw e }

Que devuelve

/so/42754270/throw_error_replace_stack.js:13 throw e ^ SyntaxError: Unexpected token k in JSON at position 0 at Object.parse (native) at Object.<anonymous> (/so/42754270/throw_error_replace_stack.js:8:13) at Module._compile (module.js:570:32) at Object.Module._extensions..js (module.js:579:10) at Module.load (module.js:487:32) at tryModuleLoad (module.js:446:12) at Function.Module._load (module.js:438:3) at Module.runMain (module.js:604:10) at run (bootstrap_node.js:394:7) at startup (bootstrap_node.js:149:9) From previous Error: JSON parse error in "/home/jim/plumbers" at Object.<anonymous> (/so/42754270/throw_error_replace_stack.js:11:20)

También tenga en cuenta que el procesamiento de la pila es simple y asume que el mensaje de error es una sola línea. Si se encuentra con mensajes de error de varias líneas, es posible que deba buscar /n at para terminar el mensaje.

¿Cómo puedo volver a emitir un error o una excepción en nodejs / javascript e incluir un mensaje personalizado?

Tengo el siguiente código

var json = JSON.parse(result);

y quise incluir el contenido del result en el mensaje de excepción en caso de que se produzca un error de análisis. Algo como esto.

1. try { 2. var json = JSON.parse(result); 3. expect(json.messages.length).to.be(1); 4. } catch(ex) { 5. throw new Error(ex.message + ". " + "JSON response: " + result); 6. }

El problema aquí es que pierdo el rastro de mi pila.

¿Hay una manera de hacerlo similar a java ?

throw new Error("JSON response: " + result, ex);


Si todo lo que desea hacer es cambiar el mensaje, simplemente puede cambiar el mensaje:

try { throw new Error("Original Error"); } catch(err) { err.message = "Here is some context -- " + err.message; throw err; }


También puede simplemente continuar lanzando el error en su cadena de intentos. Si desea modificar algo, hágalo en el camino: antes de lanzar la declaración en b.

function a() { throw new Error(''my message''); } function b() { try { a(); } catch (e) { // add / modify properties here throw e; } } function c() { try { b(); } catch (e) { console.log(e); document.getElementById(''logger'').innerHTML = e.stack; } } c();

<pre id="logger"></pre>