Estoy tratando de extender Error con ES6 y Babel. No esta funcionando.
class MyError extends Error {
constructor(m) {
super(m);
}
}
var error = new Error("ll");
var myerror = new MyError("ll");
console.log(error.message) //shows up correctly
console.log(myerror.message) //shows empty string
El objeto Error nunca obtiene el conjunto de mensajes correcto.
Ahora he visto algunas soluciones en SO ( por ejemplo aquí ), pero todas parecen muy poco ES6-y. ¿Cómo hacerlo de una manera agradable, ES6? (Eso está funcionando en Babel)
javascript
ecmascript-6
babeljs
transpiler
Karel Bílek
fuente
fuente
Respuestas:
Basado en la respuesta de Karel Bílek, haría un pequeño cambio en
constructor
:Esto se imprimirá
MyError
en la pila, y no en el genéricoError
.También agregará el mensaje de error al seguimiento de la pila, que faltaba en el ejemplo de Karel.
También lo usará
captureStackTrace
si está disponible.Con Babel 6, necesita transform-builtin-extend ( npm ) para que esto funcione.
fuente
if (typeof Error.captureStackTrace === 'function') { Error.captureStackTrace(this, this.constructor.name) } else { this.stack = (new Error(message)).stack; }
. Yo diría que es mejor usar esta función si está disponible, ya que proporciona una pila de llamadas más 'nativa' e imprime el nombre del objeto de error. Por supuesto, si está usando esto únicamente en el lado del servidor también (Nodo), entonces tampoco es un problema.this.stack = (new Error(message)).stack
te da eso ... pero en la práctica, esto probablemente no sea un gran problema.new MyError('foo') instanceof MyError === false
extendable-error-class
npmjs.com/package/extendable-error-class que es conveniente para evitar una dependencia de babel-plugin-transform-builtin-extendthis.message = message;
es redundante consuper(message);
Combinando esta respuesta , esta respuesta y este código , he creado esta pequeña clase "auxiliar", que parece funcionar bien.
Prueba en REPL
fuente
this.stack = (new Error(message)).stack;
- de lo contrario, falta el mensaje en el stacktracemessage
constructor de la pila Error, por lo que muestra el mensaje correcto en la parte superior de la pila cuando se lanza:this.stack = (new Error(message)).stack;
myerror.name
ahora devuelve "Error". No estoy seguro de si esto está relacionado con versiones posteriores de babel. Vea la respuesta de @ sukima a continuaciónPara finalmente poner esto a descansar. En Babel 6 es explícita que los desarrolladores no soportan que se extiende desde incorporada. A pesar de que este truco no ayuda con cosas como
Map
,Set
, etc. que hace el trabajo paraError
. Esto es importante ya que una de las ideas centrales de un lenguaje que puede generar una excepción es permitir errores personalizados. Esto es doblemente importante ya que las Promesas se vuelven más útiles, ya que están diseñadas para rechazar un Error .La triste verdad es que aún necesita realizar esto a la antigua usanza en ES2015.
Ejemplo en REPL de Babel
Patrón de error personalizado
Por otro lado, hay un complemento para Babel 6 para permitir esto.
https://www.npmjs.com/package/babel-plugin-transform-builtin-extend
Actualización: (a partir del 29/09/2016) Después de algunas pruebas, parece que babel.io no tiene en cuenta correctamente todas las afirmaciones (que se extienden desde un error extendido personalizado). Pero en Ember.JS extender Error funciona como se esperaba: https://ember-twiddle.com/d88555a6f408174df0a4c8e0fd6b27ce
fuente
Error.toString()
. La necesidad de hacer aros y giros especiales para lograr esto significa que la mayoría de los desarrolladores lo evitarán y recurrirán a malas prácticas como tirar cadenas en lugar de errores. O haciendo su propio mapa como objetos. ¿Por qué la necesidad de disuadir tales métodos OOP?Editar : Rompiendo cambios en Typecript 2.1
Editar la respuesta original de Lee Benson funciona un poco para mí. Esto también agrega
stack
y métodos adicionales deExtendableError
clase a la instancia.fuente
Object.setPrototypeOf
alMyError
constructor. stackoverflow.com/a/41102306/186334 github.com/Microsoft/TypeScript-wiki/blob/master/…Con los últimos cambios en babel 6, encuentro que transform-builtin-extend ya no funciona. Terminé usando este enfoque mixto:
y
Como resultado, todas estas pruebas pasan:
fuente
Citando
Aunque los códigos anteriores no puede dar salida a menos que el seguimiento de la pila
this.stack = (new Error()).stack;
oError.captureStackTrace(this, this.constructor.name);
se invoca en Babel . OMI, quizás sea un problema aquí.En realidad, el seguimiento de la pila se puede generar debajo
Chrome console
yNode.js v4.2.1
con estos fragmentos de código.Salida de
Chrome console
.Salida de
Node.js
fuente
Además de la respuesta @zangw, puede definir sus errores de esta manera:
que arrojará el nombre, el mensaje y el stacktrace correctos:
fuente
new MyError('foo') instanceof MyError === false
.Node.js v7.7.3
.Esa
class MyError extends Error {…}
sintaxis es correcta.Tenga en cuenta que los transpiladores todavía tienen problemas para heredar de objetos integrados. En tu caso,
Parece solucionar el problema.
fuente
Error.call()
me devuelve una nueva instancia de error.Dado esto, la respuesta aceptada ya no funciona, siempre se puede usar una fábrica como alternativa ( repl ):
fuente
Prefiero una sintaxis más fuerte que la descrita anteriormente. Los métodos adicionales en el tipo de error te ayudarán a crear bonito
console.log
o algo más.Para probar este código, puede ejecutar algo similar:
Ampliación de
CustomError
tipo son bienvenidos. Es posible agregar alguna funcionalidad específica al tipo extendido o anular el existente. Por ejemplo.fuente
Como @sukima menciona, no puede extender JS nativo. La pregunta del OP no puede ser respondida.
Similar a la respuesta de Melbourne2991 , utilicé una fábrica, pero seguí la recomendación de MDN para los tipos de error del cliente .
fuente
Esto funciona para mi:
fuente
Sin usar Babel, pero en ES6 simple, lo siguiente parece funcionar bien para mí:
Prueba de REPL:
Como puede ver, la pila contiene tanto el nombre del error como el mensaje. No estoy seguro de si me falta algo, pero todas las otras respuestas parecen complicar demasiado las cosas.
fuente
Mejoré un poco la solución de @Lee Benson de esta manera:
extendableError.js
un ejemplo de error
Luego, puede agrupar errores mientras tiene especificadores de opciones para decidir qué hacer de manera diferente en algunas de las situaciones específicas de su aplicación
fuente