ES6 및 Babel에서 오류를 확장하려고합니다. 작동하지 않습니다.
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
Error 객체는 올바른 메시지 세트를 얻지 못합니다.
이제 SO에 대한 몇 가지 솔루션 ( 예 : here )을 보았지만 모두 매우 ES6이 아닌 것처럼 보입니다. ES6 방식으로 좋은 방법은 무엇입니까? (바벨에서 일하고 있습니다)
답변
Karel Bí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);
이것은 MyError
generic이 아닌 스택에 인쇄 됩니다 Error
.
또한 Karel의 예제에서 누락 된 오류 추적을 스택 추적에 추가합니다.
사용 captureStackTrace
가능한 경우 에도 사용 됩니다.
답변
이 답변 , 이 답변 및 이 코드를 결합 하여이 작은 “도우미”클래스를 만들었습니다.
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);
답변
마침내 이것을 쉬게했다. 바벨 6 개발자가 명시 적입니다 지원하지 않는 내장에서 연장.이 트릭은 있지만 하지 않을 것 도움이 좋아 Map
, Set
이에 대한 작업을 수행 등 Error
. 예외를 던질 수있는 언어의 핵심 아이디어 중 하나는 맞춤 오류를 허용하는 것이므로 중요합니다. 오류 를 거부 하도록 설계되었으므로 약속이 더 유용 해지기 때문에 이것은 두 가지 중요합니다 .
슬픈 사실은 여전히 ES2015 에서이 방법을 수행해야한다는 것입니다.
맞춤 오류 패턴
class MyError {
constructor(message) {
this.name = 'MyError';
this.message = message;
this.stack = new Error().stack; // Optional
}
}
MyError.prototype = Object.create(Error.prototype);
반면에 Babel 6 용 플러그인이 있습니다.
https://www.npmjs.com/package/babel-plugin-transform-builtin-extend
업데이트 : (2016-09-29 기준) 일부 테스트 후 babel.io가 모든 어설 션을 올바르게 설명하지 않는 것으로 보입니다 (사용자 지정 확장 오류에서 끝남). 그러나 Ember.JS에서 확장 오류가 예상대로 작동합니다 : https://ember-twiddle.com/d88555a6f408174df0a4c8e0fd6b27ce
답변
편집 : Typescript 2.1의 주요 변경 사항
오류, 배열 및 맵과 같은 기본 제공 확장 기능이 더 이상 작동하지 않을 수 있습니다.
권장 사항으로, super (…) 호출 직후 프로토 타입을 수동으로 조정할 수 있습니다.
Lee Benson 원래 답변을 편집하면 약간 효과적입니다. 또한 인스턴스 stack
에 ExtendableError
클래스의 메소드를 추가 하고 추가 합니다.
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);
답변
babel 6의 최신 변경 사항으로 인해 변형 내장 확장 프로그램이 더 이상 작동하지 않습니다. 이 혼합 접근법을 사용하여 끝났습니다.
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;
과
import MyError from './MyError';
export default class MyChildError extends MyError {
constructor (message) {
super(message);
}
}
결과적으로 이러한 모든 테스트는 통과합니다.
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');
답변
class MyError extends Error {
constructor(message) {
super(message);
this.message = message;
this.name = 'MyError';
}
}
전화
this.stack = (new Error()).stack;
덕분 에 트릭이 필요하지 않습니다super()
.
위의 코드는 Babel 에서 this.stack = (new Error()).stack;
또는 Error.captureStackTrace(this, this.constructor.name);
호출 되지 않으면 스택 추적을 출력 할 수 없지만 . IMO, 여기에 하나의 문제가 있습니다.
사실, 스택 추적에서 출력을 할 수 있습니다 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);
의 출력 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)
출력 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
답변
@zangw 답변 외에도 다음과 같이 오류를 정의 할 수 있습니다.
'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');
올바른 이름, 메시지 및 스택 추적이 발생합니다.
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