que es6 error ecmascript javascript ecmascript-6 babeljs transpiler

ecmascript - Error de extensión en Javascript con sintaxis ES6 y Babel



javascript es6 pdf (13)

Estoy tratando de extender Error con ES6

Esa class MyError extends Error {…} es correcta.

Tenga en cuenta que los transpiladores todavía tienen problemas para heredar de los objetos incorporados. En tu caso,

var err = super(m); Object.assign(this, err);

Parece solucionar el problema.

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.

Prueba en Babel REPL .

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)


Además de la respuesta @zangw, puede definir sus errores de esta manera:

''use strict''; class UserError extends Error { constructor(msg) { super(msg); this.name = this.constructor.name; } } // define errors class MyError extends UserError {} class MyOtherError extends UserError {} console.log(new MyError instanceof Error); // true throw new MyError(''My message'');

que arrojará el nombre, mensaje y seguimiento de pila correctos:

MyError: My message at UserError (/Users/honzicek/Projects/api/temp.js:5:10) at MyError (/Users/honzicek/Projects/api/temp.js:10:1) at Object.<anonymous> (/Users/honzicek/Projects/api/temp.js:14:7) at Module._compile (module.js:434:26) at Object.Module._extensions..js (module.js:452:10) at Module.load (module.js:355:32) at Function.Module._load (module.js:310:12) at Function.Module.runMain (module.js:475:10) at startup (node.js:117:18) at node.js:951:3


Basado en la respuesta de Karel Bílek, haría un pequeño cambio en el constructor :

class ExtendableError extends Error { constructor(message) { super(message); this.name = this.constructor.name; if (typeof Error.captureStackTrace === ''function'') { Error.captureStackTrace(this, this.constructor); } else { this.stack = (new Error(message)).stack; } } } // now I can extend class MyError extends ExtendableError {} var myerror = new MyError("ll"); console.log(myerror.message); console.log(myerror instanceof Error); console.log(myerror.name); console.log(myerror.stack);

Esto imprimirá MyError en la pila, y no el Error genérico.

También agregará el mensaje de error al seguimiento de la pila, que faltaba en el ejemplo de Karel.

También usará captureStackTrace si está disponible.

Con Babel 6, necesita transform-builtin-extend ( npm ) para que esto funcione.


Combinando esta respuesta , esta respuesta y este código , he creado esta pequeña clase "auxiliar", que parece funcionar bien.

class ExtendableError extends Error { constructor(message) { super(); this.message = message; this.stack = (new Error()).stack; this.name = this.constructor.name; } } // now I can extend class MyError extends ExtendableError { constructor(m) { super(m); } } var myerror = new MyError("ll"); console.log(myerror.message); console.log(myerror instanceof Error); console.log(myerror.name); console.log(myerror.stack);

Prueba en REPL


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 .

function extendError(className){ function CustomError(message){ this.name = className; this.message = message; this.stack = new Error().stack; // Optional } CustomError.prototype = Object.create(Error.prototype); CustomError.prototype.constructor = CustomError; return CustomError; }


Con los últimos cambios en babel 6, encuentro que transform-builtin-extend ya no funciona. Terminé usando este enfoque mixto:

export default class MyError { constructor (message) { this.name = this.constructor.name; this.message = message; this.stack = (new Error(message)).stack; } } MyError.prototype = Object.create(Error.prototype); MyError.prototype.constructor = MyError;

y

import MyError from ''./MyError''; export default class MyChildError extends MyError { constructor (message) { super(message); } }

Como resultado, todas estas pruebas pasan:

const sut = new MyError(''error message''); expect(sut.message).toBe(''error message''); expect(sut).toBeInstanceOf(Error); expect(sut).toBeInstanceOf(MyError); expect(sut.name).toBe(''MyError''); expect(typeof sut.stack).toBe(''string''); const sut = new MyChildError(''error message''); expect(sut.message).toBe(''error message''); expect(sut).toBeInstanceOf(Error); expect(sut).toBeInstanceOf(MyError); expect(sut).toBeInstanceOf(MyChildError); expect(sut.name).toBe(''MyChildError''); expect(typeof sut.stack).toBe(''string'');


Dado esto, la respuesta aceptada ya no funciona, siempre se puede usar una fábrica como alternativa ( repl ):

function ErrorFactory(name) { return class AppError extends Error { constructor(message) { super(message); this.name = name; this.message = message; if (typeof Error.captureStackTrace === ''function'') { Error.captureStackTrace(this, this.constructor); } else { this.stack = (new Error(message)).stack; } } } } // now I can extend const MyError = ErrorFactory("MyError"); var myerror = new MyError("ll"); console.log(myerror.message); console.log(myerror instanceof Error); console.log(myerror.name); console.log(myerror.stack);


Esto funciona para mi:

/** * @class AuthorizationError * @extends {Error} */ export class AuthorizationError extends Error { message = ''UNAUTHORIZED''; name = ''AuthorizationError''; }


Para finalmente poner esto a descansar. En Babel 6 es explícito que los desarrolladores no son compatibles con la extensión desde el incorporado. Aunque este truco no ayudará con cosas como Map , Set , etc., funciona para Error . 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 Babel REPL

Patrón de error personalizado

class MyError { constructor(message) { this.name = ''MyError''; this.message = message; this.stack = new Error().stack; // Optional } } MyError.prototype = Object.create(Error.prototype);

Por otro lado, hay un complemento para Babel 6 para permitir esto.

npm

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


Prefiero una sintaxis más fuerte que la descrita anteriormente. Los métodos adicionales en el tipo de error te ayudarán a crear un bonito console.log o algo más.

export class CustomError extends Error { /** * @param {string} message * @param {number} [code = 0] */ constructor(message, code = 0) { super(); /** * @type {string} * @readonly */ this.message = message; /** * @type {number} * @readonly */ this.code = code; /** * @type {string} * @readonly */ this.name = this.constructor.name; /** * @type {string} * @readonly */ this.stack = CustomError.createStack(this); } /** * @return {string} */ toString() { return this.getPrettyMessage(); } /** * @return {string} */ getPrettyMessage() { return `${this.message} Code: ${this.code}.`; } /** * @param {CustomError} error * @return {string} * @private */ static createStack(error) { return typeof Error.captureStackTrace === ''function'' ? Error.captureStackTrace(error, error.constructor) : (new Error()).stack; } }

Para probar este código, puede ejecutar algo similar:

try { throw new CustomError(''Custom error was thrown!''); } catch (e) { const message = e.getPrettyMessage(); console.warn(message); }

La extensión del tipo CustomError es bienvenida. Es posible agregar alguna funcionalidad específica al tipo extendido o anular el existente. Por ejemplo.

export class RequestError extends CustomError { /** * @param {string} message * @param {string} requestUrl * @param {number} [code = 0] */ constructor(message, requestUrl, code = 0) { super(message, code); /** * @type {string} * @readonly */ this.requestUrl = requestUrl; } /** * @return {string} */ getPrettyMessage() { const base = super.getPrettyMessage(); return `${base} Request URL: ${this.requestUrl}.`; } }


Sin usar Babel, pero en ES6 simple, lo siguiente parece funcionar bien para mí:

class CustomError extends Error { constructor(...args) { super(...args); this.name = this.constructor.name; } }

Prueba de REPL:

> const ce = new CustomError(''foobar''); > ce.name ''CustomError'' > ce.message ''foobar'' > ce instanceof CustomError true > ce.stack ''CustomError: foobar/n at CustomError (repl:3:1)/n ...''

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.


Quoting

class MyError extends Error { constructor(message) { super(message); this.message = message; this.name = ''MyError''; } }

No hay necesidad de this.stack = (new Error()).stack; truco gracias a la llamada super() .

Aunque los códigos anteriores no pueden generar el seguimiento de la pila a menos que this.stack = (new Error()).stack; o Error.captureStackTrace(this, this.constructor.name); se invoca en Babel . OMI, tal vez sea un problema aquí.

En realidad, el seguimiento de la pila se puede generar en la Chrome console y Node.js v4.2.1 con estos fragmentos de código.

class MyError extends Error{ constructor(msg) { super(msg); this.message = msg; this.name = ''MyError''; } }; var myerr = new MyError("test"); console.log(myerr.stack); console.log(myerr);

Salida de la Chrome console .

MyError: test at MyError (<anonymous>:3:28) at <anonymous>:12:19 at Object.InjectedScript._evaluateOn (<anonymous>:875:140) at Object.InjectedScript._evaluateAndWrap (<anonymous>:808:34) at Object.InjectedScript.evaluate (<anonymous>:664:21)

Salida de Node.js

MyError: test at MyError (/home/bsadmin/test/test.js:5:8) at Object.<anonymous> (/home/bsadmin/test/test.js:11:13) at Module._compile (module.js:435:26) at Object.Module._extensions..js (module.js:442:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:311:12) at Function.Module.runMain (module.js:467:10) at startup (node.js:134:18) at node.js:961:3


Editar : Rompiendo cambios en Typecript 2.1

Es posible que las extensiones integradas como Error, Array y Mapa ya no funcionen.

Como recomendación, puede ajustar manualmente el prototipo inmediatamente después de cualquier super (...) llamada.

Editar la respuesta original de Lee Benson funciona un poco para mí. Esto también agrega stack y métodos adicionales de la clase ExtendableError a la instancia.

class ExtendableError extends Error { constructor(message) { super(message); Object.setPrototypeOf(this, ExtendableError.prototype); this.name = this.constructor.name; } dump() { return { message: this.message, stack: this.stack } } } class MyError extends ExtendableError { constructor(message) { super(message); Object.setPrototypeOf(this, MyError.prototype); } } var myerror = new MyError("ll"); console.log(myerror.message); console.log(myerror.dump()); console.log(myerror instanceof Error); console.log(myerror.name); console.log(myerror.stack);