예외객체를 세분화하는것은 발생된 예외정보를 자세히 알수있는 장점이 있지만 세분화될수록 종류가 많아져 가독성이 떨어지는 단점이 동반된다.
예외를 세분화하되 예외를 처리하는 곳에서는 단순화하여 예외발생에대한 필수정보만 알수있도록 해도 충분하다. 이것을 예외감싸기라 한다.
class ReadError extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = 'ReadError';
}
}
class ValidationError extends Error { /*...*/ }
class PropertyRequiredError extends ValidationError { /* ... */ }
ReadError객체는 세분화된 에러객체 ValidationError와 PropertyRequiredError를 감싸는 용도의 에러객체다.
ValidationError와 PropertyRequiredError는 필요하다 왜냐하면 세분화해서 예외에대한 정보를 모아야 한다.
예외정보를 다시 ReadError로 모아서 예외를 던지는 용도인 것이다.
let json = `{ "name": "John"}`;
class ReadError extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = 'ReadError';
}
}
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 validateUser(user){
if(user.name ==undefined){
throw new PropertyRequiredError('name');
}
if(user.age ==undefined){
throw new PropertyRequiredError('age');
}
}
function readUser (jsonStr){
let user;
try {
user = JSON.parse(jsonStr);
} catch (error) {
if(error instanceof SyntaxError){
throw new ReadError("SyntaxError",error);
}else{
throw error;
}
}
try {
validateUser(user);
} catch (error) {
if(error instanceof ValidationError){
throw new ReadError("ValidationError",error);
}else{
throw error;
}
}
return user;
}
try {
let user = readUser(json);
} catch (error) {
if(error instanceof ReadError){
console.log(error);
console.log("Original error: " + error.cause);
}else{
throw error;
}
}
catch블럭에는 ReadError만 있으면서도 발생된 에러객체정보를 자세히 가지고 있다. 에러감싸기의 효과다.