ê°ë°ì íë¤ ë³´ë©´ ìì²´ ìë¬ í´ëì¤ê° íìí ê²½ì°ê° ì¢
ì¢
ìê¹ëë¤. ë¤í¸ìí¬ ê´ë ¨ ìì
ì¤ ìë¬ê° ë°ìíë¤ë©´ HttpError, ë°ì´í°ë² ì´ì¤ ê´ë ¨ ìì
ì¤ ìë¬ê° ë°ìíë¤ë©´ DbError, ê²ì ê´ë ¨ ìì
ì¤ ìë¬ê° ë°ìíë¤ë©´ NotFoundError를 ì¬ì©íë ê²ì´ ì§ê´ì ì´ê¸° ë문ì´ì£ .
ì§ì ìë¬ í´ëì¤ë¥¼ ë§ë ê²½ì°, ì´ ìë¬ë¤ì messageì´ë name, ê°ë¥íë¤ë©´ stack íë¡í¼í°ë¥¼ ì§ìí´ì¼ í©ëë¤. ë¬¼ë¡ ì´ë° íë¡í¼í° ì´ì¸ìë ë¤ë¥¸ íë¡í¼í°ë¥¼ ì§ìí ì ììµëë¤. HttpError í´ëì¤ì ê°ì²´ì statusCode íë¡í¼í°ë¥¼ ë§ë¤ê³ 404ë 403, 500ê°ì ì«ì를 ê°ì¼ë¡ ì§ì í ì ìì ê²ëë¤.
ìì ë°°ì´ ë°ì ê°ì´ throwì ì¸ìì ìë¬´ë° ì ì½ì´ ì기 ë문ì 커ì¤í
ìë¬ í´ëì¤ë ë°ëì Error를 ììí íìê° ììµëë¤. ê·¸ë ì§ë§ Error를 ììë°ì 커ì¤í
ìë¬ í´ëì¤ë¥¼ ë§ë¤ê² ëë©´ obj instanceof Error를 ì¬ì©í´ì ìë¬ ê°ì²´ë¥¼ ìë³í ì ìë¤ë ì¥ì ì´ ìê¹ëë¤. ì´ë° ì¥ì ë문ì 맨ë
ìì 커ì¤í
ìë¬ ê°ì²´ë¥¼ ë§ëë ê²ë³´ë¤ Error를 ììë°ì ìë¬ ê°ì²´ë¥¼ ë§ëë ê²ì´ ë«ìµëë¤.
ì í리ì¼ì´ì
í¬ê¸°ê° ì ì 커ì§ë©´ ì°ë¦¬ê° ë§ë¤ê² ë 커ì¤í
ìë¬ í´ëì¤ë¤ì ìì°ì¤ë ê³ì¸µ 구조를 íì±íê² ë©ëë¤. HttpTimeoutErrorë HttpError를 ììë°ë ìì¼ë¡ ë§ì´ì£ .
ìë¬ íì¥í기
ì¬ì©ì ë°ì´í°ê° ì ì¥ë JSONì ì½ë í¨ì readUser(json)ê° ìë¤ê³ í´ë´
ìë¤.
ì í¨í jsonì ë¤ìê³¼ ê°ì ííì´ì´ì¼ í©ëë¤.
let json = `{ "name": "John", "age": 30 }`;
readUser ë´ë¶ìì JSON.parse를 ì´ì©íê² ë©ëë¤. ë°ë¼ì ì못ë íìì jsonì´ ë¤ì´ì¤ë©´ SyntaxErrorê° ë°ìíê² ì£ . ê·¸ë°ë° ì¸ìë¡ ë°ì ë°ì´í°ê° JSON íìì´ê¸´ íì§ë§, ì í¨í ì¬ì©ìì¼ ê²ì´ë¼ë ë³´ì¥ì ììµëë¤. ì¬ì©ì ë°ì´í°ë¼ë©´ íìì ì¼ë¡ ìì´ì¼ í nameì´ë ageê° ëë½ëìì ì ìì£ .
ë°ë¼ì readUser(json)ì JSON íìì ë°ì´í°ë¥¼ ì½ì ì ìì ë¿ë§ ìëë¼, ë°ì´í°ë¥¼ 'ê²ì¦âí ì ìì´ì¼ í©ëë¤. íì íë¡í¼í°ê° ìê±°ë, ì íìì ë§ì§ ìì¼ë©´ ìë¬ë¥¼ ë°ììí¬ ì ìì´ì¼ íì£ . ê·¸ë°ë° ì´ë ë°ìíë ìë¬ë SyntaxErrorê° ìëëë¤. JSON íìì ë§ì§ë§, ìì²´ 기ì¤ì ë§ì§ ì기 ë문ì ë°ìí ìë¬ì´ë¯ë¡ ì í ë¤ë¥¸ ì¢
ë¥ì ìë¬ì´ì£ . ì§ê¸ë¶í´ ì´ ìë¬ë¥¼ ValidationErrorë¼ê³ ë¶ë¥´ê² ìµëë¤. ì ì´ì ValidationError를 ìí í´ëì¤ë¥¼ ë§ë¤ì´ë´
ìë¤.
ValidationError í´ëì¤ì 문ì ê° ëë íë ì ë³´ê° ì ì¥ëì´ì¼ í©ëë¤. ë´ì¥ í´ëì¤ Error를 ììë°ì ValidationError í´ëì¤ë¥¼ ë§ë¤ì´ë´
ìë¤.
ê·¸ ì ì 먼ì ì ì ìë ì½ëë¡ Error í´ëì¤ê° ì´ë»ê² ìê²¼ëì§ ì´í´ë³´ê² ìµëë¤.
// ìë°ì¤í¬ë¦½í¸ ìì²´ ë´ì¥ ìë¬ í´ëì¤ Errorì 'ìë ì½ë'
class Error {
constructor(message) {
this.message = message;
this.name = "Error"; // (nameì ë´ì¥ ìë¬ í´ëì¤ë§ë¤ ë¤ë¦
ëë¤.)
this.stack = <call stack>; // stackì íì¤ì ìëì§ë§, ëë¤ì íê²½ì´ ì§ìí©ëë¤.
}
}
ì´ì ValidationErrorìì Error를 ììë°ìë³´ê² ìµëë¤.
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)ìì ìíë ê°ì¼ë¡ ì¬ì¤ì í´ì£¼ììµëë¤.
ì´ì readUser(json) ììì ValidationError를 ì¬ì©í´ ë´
ìë¤.
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
// ì¬ì©ë²
function readUser(json) {
let user = JSON.parse(json);
if (!user.age) {
throw new ValidationError("No field: age");
}
if (!user.name) {
throw new ValidationError("No field: name");
}
return user;
}
// try..catchì readUser를 í¨ê» ì¬ì©í ìì
try {
let user = readUser('{ "age": 25 }');
} catch (err) {
if (err instanceof ValidationError) {
alert("Invalid data: " + err.message); // Invalid data: No field: name
} else if (err instanceof SyntaxError) { // (*)
alert("JSON Syntax Error: " + err.message);
} else {
throw err; // ìë ¤ì§ì§ ìì ìë¬ë ì¬ëì§ê¸° í©ëë¤. (**)
}
}
ì´ì try..catch ë¸ë¡ìì 커ì¤í
ìë¬ ValidationErrorì JSON.parseìì ë°ìíë SyntaxError ë ë¤ë¥¼ ì²ë¦¬í ì ìê² ëììµëë¤.
ì´ ê³¼ì ìì instanceofë¡ ìë¬ ì íì íì¸((*))íììµëë¤.
ìë¬ ì í íì¸ì instanceof ë§ê³ ë¤ìê³¼ ê°ì´ err.nameì ì¬ì©í´ë ê°ë¥í©ëë¤.
// ...
// (err instanceof SyntaxError) ëì ì¬ì© ê°ë¥
} else if (err.name == "SyntaxError") { // (*)
// ...
ê·¸ë°ë° ìë¬ ì í íì¸ì err.nameë³´ë¤ë instanceof를 ì¬ì©íë ê² í¨ì¬ ì¢ìµëë¤. ëì¤ì ValidationError를 íì¥íì¬ PropertyRequiredError ê°ì ìë¡ì´ íì¥ ìë¬ë¥¼ ë§ë¤ê² ë í
ë°, instanceofë ìë¡ì´ ìì í´ëì¤ììë ëìí기 ë문ì
ëë¤.
catchì ìë ¤ì§ì§ ìì ìë¬ê° ìì ë ì´ ìë¬ë ì¬ ëì§ê¸° ëë¤ë ì ((**)) ëí 주목í´ì ë´ì£¼ì기 ë°ëëë¤. catch ë¸ë¡ìì ì í¨ì± ê²ì¬ì ë¬¸ë² ì¤ë¥ë§ ì²ë¦¬íê³ , ë¤ë¥¸ ì¢
ë¥ì ìë¬ë ë°ì¼ë¡ ëì ¸ì¼ í©ëë¤.
ë ê¹ê² ììí기
ìì ë§ë ValidationError í´ëì¤ë ë무 í¬ê´ì ì´ì´ì ëê° ì못ë íë¥ ì´ ììµëë¤. ê¼ íìí íë¡í¼í°ê° ëë½ëê±°ë ageì 문ìì´ ê°ì´ ë¤ì´ê°ë ê²ì²ë¼ íìì´ ì못ë ê²½ì°ë¥¼ ì²ë¦¬í ì ìì£ . íì íë¡í¼í°ê° ìë ê²½ì°ì ëìí ì ìëë¡ ì¢ ë 구체ì ì¸ í´ëì¤ PropertyRequiredError를 ë§ë¤ì´ ë´
ìë¤. PropertyRequiredErrorì ëë½ë íë¡í¼í°ì ëí ì¶ê° ì ë³´ê° ë´ê²¨ì¼ í©ëë¤.
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);
if (!user.age) {
throw new PropertyRequiredError("age");
}
if (!user.name) {
throw new PropertyRequiredError("name");
}
return user;
}
// try..catchì readUser를 í¨ê» ì¬ì©íë©´ ë¤ìê³¼ ê°ìµëë¤.
try {
let user = readUser('{ "age": 25 }');
} catch (err) {
if (err instanceof ValidationError) {
alert("Invalid data: " + err.message); // Invalid data: No property: name
alert(err.name); // PropertyRequiredError
alert(err.property); // name
} else if (err instanceof SyntaxError) {
alert("JSON Syntax Error: " + err.message);
} else {
throw err; // ìë ¤ì§ì§ ìì ìë¬ë ì¬ëì§ê¸° í©ëë¤.
}
}
ìë¡ê² ë§ë í´ëì¤ PropertyRequiredErrorë ì¬ì©í기 ì½ìµëë¤. new PropertyRequiredError(property)ì²ë¼ íë¡í¼í° ì´ë¦ì ì ë¬íê¸°ë§ íë©´ ëì£ . ì¬ëì´ ì½ì ì ìë messageë ìì±ìê° ììì ë§ë¤ì´ì¤ëë¤.
ì¬ê¸°ì 주목í ì ì PropertyRequiredError ìì±ì ììì this.nameì ìëì¼ë¡ í ë¹í´ 주ìë¤ë ê²ì
ëë¤. ê·¸ë°ë° ì´ë ê² ë§¤ë² ì»¤ì¤í
ìë¬ í´ëì¤ì ìì±ì ììì this.name를 í ë¹í´ 주ë ê²ì ê·ì°®ì ìì
ì
ëë¤. ì´ë° ë²ê±°ë¡ì´ ìì
ì â기본 ìë¬â í´ëì¤ë¥¼ ë§ë¤ê³ 커ì¤í
ìë¬ë¤ì´ ì´ í´ëì¤ë¥¼ ììë°ê² íë©´ í¼í ì ììµëë¤. 기본 ìë¬ì ìì±ìì this.name = this.constructor.name를 ì¶ê°íë©´ ëì£ .
기본 ìë¬ í´ëì¤ë¥¼ MyErrorë¼ê³ ë¶ë¥´ê² ìµëë¤.
MyError를 ì¬ì©íë©´ ë¤ìê³¼ ê°ì´ 커ì¤í
ìë¬ í´ëì¤ë¥¼ ê°ê²°íê² í ì ììµëë¤.
class MyError extends Error {
constructor(message) {
super(message);
this.name = this.constructor.name;
}
}
class ValidationError extends MyError { }
class PropertyRequiredError extends ValidationError {
constructor(property) {
super("No property: " + property);
this.property = property;
}
}
// ì ëë¡ ë ì´ë¦ì´ ì¶ë ¥ë©ëë¤.
alert( new PropertyRequiredError("field").name ); // PropertyRequiredError
"this.name = ..." ì´ ì¬ë¼ì¡ê¸° ë문ì ValidationErrorê°ì 커ì¤í
ìë¬ì ìì±ìê° ë ê¹ëí´ì§ ê²ì íì¸í ì ììµëë¤.
ìì¸ ê°ì¸ê¸°
í¨ì readUserë âì¬ì©ì ë°ì´í°ë¥¼ ì½ê¸°â ìí ì©ëë¡ ë§ë¤ì´ì¡ìµëë¤. ê·¸ë°ë° ì¬ì©ì ë°ì´í°ë¥¼ ì½ë ê³¼ì ìì ë¤ë¥¸ ì¤ë¥ê° ë°ìí ì ììµëë¤. ì§ê¸ ë¹ì¥ì SyntaxErrorì ValidationError를 ì¬ì©í´ ìë¬ë¥¼ ì²ë¦¬íê³ ìëë°, ìì¼ë¡ readUserê° ë 커ì§ë©´ ë¤ë¥¸ 커ì¤í
ìë¬ í´ëì¤ë¥¼ ë§ë¤ì´ì¼ í ê²ëë¤.
readUser를 í¸ì¶íë ê³³ìì ìë¡ê² ë§ë¤ì´ì§ 커ì¤í
ìë¬ë¤ì ì²ë¦¬í ì ìì´ì¼ í©ëë¤. ê·¸ë°ë° ì§ê¸ì catch ë¸ë¡ ìì if문 ì¬ë¬ ê°ë¥¼ ë£ì´ ì¢
ë¥ë¥¼ ì ì ìë ìë¬ë¥¼ ì²ë¦¬íê³ , ê·¸ë ì§ ìì ìë¬ë ë¤ì ëì§ê¸°ë¥¼ í´ ì²ë¦¬íê³ ìë ì¤ì ì
ëë¤.
íì¬ ìë¬ ì²ë¦¬ ì¤í¤ë§ë ë¤ìê³¼ ê°ìµëë¤.
try {
...
readUser() // ì ì¬ì ìë¬ ë°ìì²
...
} catch (err) {
if (err instanceof ValidationError) {
// validation ìë¬ ì²ë¦¬
} else if (err instanceof SyntaxError) {
// ë¬¸ë² ìë¬ ì²ë¦¬
} else {
throw err; // ì ì ìë ìë¬ë ë¤ì ëì§ê¸° í¨
}
}
ì ì¤í¤ë§ì ë ì¢ ë¥ì ìë¬ë§ ëì ìë¤ì. ê·¸ë°ë° ìë¬ì ì¢ ë¥ë ë ì¶ê°ë ì ììµëë¤.
ì´ì¯¤ ëë©´ "미ëì readUser 기ë¥ì´ 커ì§ë©´ì ìë¬ ì¢
ë¥ê° ë§ìì§ í
ë° ê·¸ëë§ë¤ ìë¬ ì¢
ë¥ì ë°ë¼ ìë¬ ì²ë¦¬ ë¶ê¸°ë¬¸ì ë§¤ë² ì¶ê°í´ì¼ íë?"ë¼ë ìë¬¸ì´ ì길 ì ììµëë¤.
ë³´íµì ê·¸ë ì§ âììµëë¤â. ì¤ì ì°ë¦¬ê° íìë¡ íë ì ë³´ë âë°ì´í°ë¥¼ ì½ì ëâ ìë¬ê° ë°ìíëì§ì ëí ì¬ë¶ì ëë¤. ì ìë¬ê° ë°ìíëì§ì ìì¸í ì¤ëª ì ëë¶ë¶ì ê²½ì° íìíì§ ììµëë¤. íìí ë ìë¬ ì¸ë¶ì¬íì ëí ì 보를 ì»ì ì ìë ë°©ë²ì´ ìë¤ë©´ ë ì¢ê² ì§ë§ ë§ì´ì£ .
ì´ë° ìë¬ ì²ë¦¬ 기ì ì 'ìì¸ ê°ì¸ê¸°(wrapping exception)'ë¼ê³ ë¶ë¦ ëë¤. ìì¸ ê°ì¸ê¸°ë ë¤ìê³¼ ê°ì ììë¡ ì§íë©ëë¤.
- 'ë°ì´í° ì½ê¸°âì ê°ì í¬ê´ì ì¸ ìë¬ë¥¼ ëë³íë ìë¡ì´ í´ëì¤
ReadError를 ë§ëëë¤. - í¨ì
readUserë°ìíValidationError,SyntaxErrorë±ì ìë¬ëreadUserë´ë¶ìì ì¡ê³ ì´ëReadError를 ìì±í©ëë¤. ReadErrorê°ì²´ìcauseíë¡í¼í°ì ì¤ì ìë¬ì ëí ì°¸ì¡°ê° ì ì¥ë©ëë¤.
ì´ë ê² ìì¸ ê°ì¸ê¸° 기ì ì ì¨ ì¤í¤ë§ë¥¼ ë³ê²½íë©´ readUser를 í¸ì¶íë ì½ëìì ReadErrorë§ íì¸íë©´ ë©ëë¤. ë°ì´í°ë¥¼ ì½ì ë ë°ìíë ìë¬ ì¢
ë¥ ì 체를 íì¸íì§ ììë ëì£ . ì¶ê° ì ë³´ê° íìí ê²½ì°ì cause íë¡í¼í°ë¥¼ íì¸íë©´ ë©ëë¤.
ì´ì ì¤ì ë¡ ReadError를 ì ìíê³ ì´ë¥¼ ì¬ì©í´ë³´ëë¡ í©ìë¤. ReadErrorëreadUserì try..catch ììì ë¤ìê³¼ ê°ì ííë¡ ì¬ì©í ì ììµëë¤.
class ReadError extends Error {
constructor(message, cause) {
super(message);
this.cause = cause;
this.name = 'ReadError';
}
}
class ValidationError extends Error { /*...*/ }
class PropertyRequiredError extends ValidationError { /* ... */ }
function validateUser(user) {
if (!user.age) {
throw new PropertyRequiredError("age");
}
if (!user.name) {
throw new PropertyRequiredError("name");
}
}
function readUser(json) {
let user;
try {
user = JSON.parse(json);
} catch (err) {
if (err instanceof SyntaxError) {
throw new ReadError("Syntax Error", err);
} else {
throw err;
}
}
try {
validateUser(user);
} catch (err) {
if (err instanceof ValidationError) {
throw new ReadError("Validation Error", err);
} else {
throw err;
}
}
}
try {
readUser('{ì못ë íìì json}');
} catch (e) {
if (e instanceof ReadError) {
alert(e);
// Original error: SyntaxError: Unexpected token b in JSON at position 1
alert("Original error: " + e.cause);
} else {
throw e;
}
}
ì´ì readUserë ììì ì¤ëª
í ê²ì²ë¼ ëìí©ëë¤. Syntax ìë¬ë Validation ìë¬ê° ë°ìí ê²½ì° í´ë¹ ìë¬ ì체를 ë¤ì ëì§ê¸° íì§ ìê³ ReadError를 ëì§ê² ë©ëë¤.
ì´ë ê² ëë©´, readUser를 í¸ì¶íë ë°ê¹¥ ì½ëìì instanceof ReadError ë± íëë§ íì¸íë©´ ë©ëë¤. ìë¬ ì²ë¦¬ ë¶ê¸°ë¬¸ì ì¬ë¬ ê° ë§ë¤ íìê° ìì´ì§ëë¤.
'ìì¸ ê°ì¸ê¸°âë ì´ë¦ì ì¢
ë¥ë³ ìë¬ë¥¼ ì¢ ë ì¶ìì ì¸ ìë¬, ReadErrorì íëë¡ ëª¨ì(wrap) ì²ë¦¬í기 ë문ì ë¶ì¬ì¡ìµëë¤. ì´ë° 기ë²ì ê°ì²´ ì§í¥ íë¡ê·¸ëë°ìì ë리 ì°ì´ë í¨í´ì
ëë¤.
ìì½
- 커ì¤í
í´ëì¤ë
Errorë ë¤ë¥¸ ë´ì¥ ìë¬ í´ëì¤ë¥¼ ììë°ì ë§ë¤ ì ììµëë¤. ì´ësuper를 í¸ì¶í´ì¼ íë¤ë ì ê³¼nameíë¡í¼í°ë¥¼ ì ê²½ ì¨ì¼ íë¤ë ì ì ìì§ ë§ì¸ì. instanceof를 ì¬ì©íë©´ ìë¬ ì¢ ë¥ë¥¼ íë³í ì ììµëë¤. ììë í´ëì¤ìë ë§ì°¬ê°ì§ì£ . ê·¸ë°ë° ìëíí° ë¼ì´ë¸ë¬ë¦¬ìì ì¨ ìë¬ ê°ì²´ë í´ëì¤ë¥¼ ììë´ë ê²ì´ ì½ì§ ììµëë¤. ì´ë´ ënameíë¡í¼í°ë¥¼ ì¬ì©í´ ì¤ë¥ ì¢ ë¥ë¥¼ íì¸í ì ììµëë¤.- ìì¸ ê°ì¸ê¸°ë ë리 ìë ¤ì§ ìì¸ ì²ë¦¬ 기ì ì
ëë¤. ìì¸ ê°ì¸ê¸°ë¥¼ ì ì©í í¨ììì 모ë ìë¬ë¥¼ ì¢
ë¥ë³ë¡ ì²ë¦¬íì§ ììµëë¤. ëì 모ë ìë¬ë¥¼ í¬í¨í ì ìë ì¶ì ìë¬ë¥¼ íë ë§ë¤ê³ , ìë¬ê° ë°ìíë©´ ì´ ì¶ì ìë¬ë¥¼ ëì§ëë¡ í©ëë¤. ì¶ì ìë¬ë¥¼ ëì§ ë ì¤ì ë°ìí ìë¬ë¥¼ ì¶ì ìë¬ì íë¡í¼í°(
err.cause)ë¡ ë기면 구체ì ì¸ ìë¬ ì 보를 í¨ê» ëê²¨ì¤ ì ìëë°, ë°ëì ì´ íë¡í¼í°ê° ìì´ì¼ íë ê²ì ìëëë¤.
ëê¸
<code>í그를, ì¬ë¬ ì¤ë¡ 구ì±ë ì½ë를 ì½ì íê³ ì¶ë¤ë©´<pre>í그를 ì´ì©íì¸ì. 10ì¤ ì´ìì ì½ëë plnkr, JSBin, codepen ë±ì ìëë°ì¤ë¥¼ ì¬ì©íì¸ì.