使用ES6语法和Babel扩展Javascript中的错误

Kar*_*lek 128 javascript transpiler ecmascript-6 babeljs

我试图用ES6和Babel扩展Error.它没有成功.

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
Run Code Online (Sandbox Code Playgroud)

Error对象永远不会获得正确的消息集.

试试Babel REPL.

现在我已经在SO上看到了一些解决方案(例如这里),但它们看起来都非常非ES6-y.如何以漂亮的ES6方式做到这一点?(那是在Babel工作)

Lee*_*son 184

根据KarelBílek的回答,我会对以下内容做一点改动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);
Run Code Online (Sandbox Code Playgroud)

这将打印MyError在堆栈中,而不是通用Error.

它还会将错误消息添加到堆栈跟踪中 - 这是Karel示例中缺少的.

captureStackTrace如果它可用,它也将使用.

使用Babel 6,您需要使用transform-b​​uiltin-extend(npm)才能工作.

  • 这在Babel 6中不起作用:MyError的新MyError('foo')实例=== false` (6认同)
  • 这段代码预编译为babel作为NPM模块:`extendedable-error-class`https://www.npmjs.com/package/extendable-error-class,方便避免依赖babel-plugin-transform-b​​uiltin -延伸 (5认同)
  • @MichaelYounkin我认为这不值得投票.OP讨论了扩展ES6中的错误.遵循该逻辑,至少有一个浏览器缺少几乎所有的ES6.我的解决方案(添加了func检查)在最广泛使用的浏览器中提供本机覆盖,在其他所有浏览器中提供回退,并在Node.js中提供100%的覆盖率.我同意,如果你的错误类名一致,那么`this.stack =(new Error(message)).stack`可以帮助你......但在实践中,这可能不是什么大不了的事. (4认同)
  • `this.message = message;`与`super(message);`是多余的 (3认同)

Kar*_*lek 39

结合这个答案,这个答案这个代码,我已经做了这个小的"助手"类,似乎工作正常.

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);
Run Code Online (Sandbox Code Playgroud)

尝试REPL

  • 同样的问题,使用instanceof CustomError不起作用,如果你不能使用instanceof,那么重点是什么. (4认同)
  • 我怀疑这不能按需要工作,因为如果你这样做:console.log(myerror instanceof ExtendableError); 它仍然说错误.. (3认同)

Suk*_*ima 26

最后让这个休息.在通天六是明确的,开发商不支持从内置的扩展.虽然这一招不会的东西像帮助Map,Set等等.它的工作Error.这很重要,因为可以引发异常的语言的核心思想之一是允许自定义错误.这是非常重要的,因为Promises变得更有用,因为它们旨在拒绝错误.

可悲的事实是,你仍然需要在ES2015中以旧方式执行此操作.

Babel REPL中的示例

自定义错误模式

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

另一方面,有一个Babel 6的插件允许这样做.

https://www.npmjs.com/package/babel-plugin-transform-b​​uiltin-extend

更新:(截至2016-09-29)经过一些测试后,看来babel.io没有正确解释所有断言(从自定义扩展错误扩展).但在Ember.JS扩展错误按预期工作:https://ember-twiddle.com/d88555a6f408174df0a4c8e0fd6b27ce


Art*_*yan 14

编辑:打破Typescript 2.1中的更改

扩展错误,数组和映射等内置函数可能不再有效.

作为建议,您可以在任何超级(...)调用后立即手动调整原型.

编辑Lee Benson的原始答案对我来说有点作用.这也为实例添加stackExtendableError类的其他方法.

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);
Run Code Online (Sandbox Code Playgroud)


Die*_*rri 10

随着babel 6的最新变化,我发现transform-b​​uiltin-extend不再有效.我最终使用这种混合方法:

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;
Run Code Online (Sandbox Code Playgroud)

import MyError from './MyError';

export default class MyChildError extends MyError {
    constructor (message) {
        super(message);
    }
}
Run Code Online (Sandbox Code Playgroud)

结果所有这些测试通过:

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');
Run Code Online (Sandbox Code Playgroud)


zan*_*ngw 5

报价单

class MyError extends Error {
  constructor(message) {
    super(message);
    this.message = message;
    this.name = 'MyError';
  }
}
Run Code Online (Sandbox Code Playgroud)

无需this.stack = (new Error()).stack;打招呼super()

尽管以上代码无法输出堆栈跟踪,除非在Babel中调用this.stack = (new Error()).stack;或。海事组织,这可能是这里的一个问题。Error.captureStackTrace(this, this.constructor.name);

实际上,堆栈跟踪可以在此代码段下Chrome console以及Node.js v4.2.1与此代码段一起输出。

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);
Run Code Online (Sandbox Code Playgroud)

输出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)
Run Code Online (Sandbox Code Playgroud)

输出 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
Run Code Online (Sandbox Code Playgroud)