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>