Error 클래스 구조
// 자바스크립트 자체 내장 에러 클래스 Error의 '슈도 코드'
class Error {
constructor(message) {
this.message = message; // 에러 메시지
this.name = "Error"; // 에러로 표시될 이름
this.stack = [call stack]; // stack은 표준은 아니지만, 대다수 환경이 지원함
}
}
- message: 에러 객체안에 들어있는 에러 메시지를 갖는 프로퍼티
- name: 에러가 발생할 때 ReferenceError와 같이 에러의 이름을 표시해 주는 프로퍼티
- stack: 에러 전에 있는 call stack들을 갖는 프로퍼티
class ValidationError extends Error {
constructor(message) {
super(message); // (1)
this.name = "ValidationError"; // (2)
}
}
function test() {
throw new ValidationError("에러 발생!");
}
try {
test();
} catch(err) {
alert(err.message); // 에러 발생!
alert(err.name); // ValidationError
alert(err.stack); // 각 행 번호가 있는 중첩된 호출들의 목록
}
(1)에서 부모 생성자를 호출하고 있다는 것에 주목하자. 자바스크립트에서는 자식 생성자 안에서 super를 반드시 호출해야 한다. message 프로퍼티는 부모 생성자에서 설정되기 때문이다.
부모 생성자에선 message뿐만 아니라 name 프로퍼티도 설정("Error")하기 때문에, (2)에서 원하는 값으로 재설정해주었다.
더 깊게 상속하기
너무 포괄적이라서 자세한 에러를 만들 수 있음
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
// 위에 커스텀에러를 한 번 더 확장시킨다
class PropertyRequiredError extends ValidationError {
constructor(property) {
super("No property: " + property);
this.name = "PropertyRequiredError";
this.property = property;
}
}
// 사용법
function readUser(json) {
let user = JSON.parse(json);
console.log(user);
if (!user.age && user.name) {
throw new PropertyRequiredError("age");
} else if (user.age && !user.name) {
throw new PropertyRequiredError("name");
} else {
throw new ValidationError("❗️ Validation ❗️");
}
return user;
}
function whatError(data) {
try {
let user = readUser(data);
} catch (err) {
if (err instanceof PropertyRequiredError) {
console.log("Invalid data: " + err.message);
console.log(err.name); // PropertyRequiredError
console.log(err.property); // name
} else if (err instanceof ValidationError) {
console.log("Invalid data: " + err.message);
console.log(err.name);
console.log(err.property);
} else if (err instanceof SyntaxError) {
console.log("JSON Syntax Error: " + err.message);
} else {
throw err; // 알려지지 않은 에러는 재던지기 한다.
}
}
}
whatError('{ "age": 25 }');
/*{ age: 25 }
Invalid data: No property: name
PropertyRequiredError
name */
console.log("-----------");
whatError("{ }");
/*{}
Invalid data: ❗️ Validation ❗️
ValidationError
undefined */
예시들
interface CustomError extends Error {
// name: string;
// message: string;
// stack?: string; - Error 인터페이스 프로퍼티들을 직접 쓰거나 아니면 상속해준다.
response?: {
data: any;
status: number;
headers: string;
};
}
try {
await axios.get('/user/12345');
} catch (err: unknown) {
const customErr = err as CustomError; // 타입 단언한 것을 변수에 넣어서 뒤에서 자주 쓰이면 재사용 될 수 있게
console.error(customErr.response?.data);
console.error(customErr.response?.status);
console.error(customErr.response?.headers);
}
export class ValidationError extends Error {
constructor(message: string) {
super(message);
this.name = this.constructor.name;
}
}
export class CalculateError extends Error {
constructor(message: string) {
super(message);
this.name = this.constructor.name;
}
}