예상치 못한 에러가 발생하면, 스크립트는 즉시 중단되고 콘솔에 에러가 출력된다.
하지만 스크립트가 죽는경우는 최악의 경우이기 때문에, 에러 발생 소지가 있는 곳에서 try.. catch 구문을 통해 발생한 에러를 핸들링할 수 있다.
try 구문에는 실행가능한 코드만 동작한다.
코드를 읽는 중에 발생하는 에러를 parse-time error 라고하고,
try 구문 내용이 유효한 코드만 에러를 처리할 수 있다.
이런 에러를 runtime error 혹은 exception 이라고 한다.
에러처리가 안되는 경우
scheduled 된 코드에서 발생한 예외는 잡을 수 없다.
콜백함수 내의 코드는 실행될 시점에는 try.. catch문 바깥영역이기 때문이다.
try {
setTimeout(function() {
noSuchVariable; // 스크립트는 여기서 죽습니다.
}, 1000);
} catch (e) {
alert( "작동 멈춤" );
}
그래서 아래와같이 작성해아한다.
setTimeout(function() {
try {
noSuchVariable; // 이제 try..catch에서 에러를 핸들링 할 수 있습니다!
} catch {
alert( "에러를 잡았습니다!" );
}
}, 1000);
Error 객체
1. name : 없다면 ReferenceError 가 이름
2. message : 에러의 상세내용을 담고있는 메세지
+ stack : 호출스택, 에러를 유발한 중첩 호출들의 순서 정보를 가진 문자열로 디버깅 목적으로 사용된다.
에러에대한 정보가 필요하지 않다면, 생략할 수 있다
try {
// ...
} catch { // <-- (err) 없이 쓸 수 있음
// ...
}
에러 객체는 name 과 message를 참조할 수 있다.
try {
JSON.parse("{ 잘못된 형식의 json o_O }");
} catch(e) {
alert(e.name); // SyntaxError
alert(e.message); // Unexpected token b in JSON at position 2
}
여기서 흔히 axios를 통한 통신에러는 AxiosError 객체가 던져지는데,
서버에서 에러 status와 함께 보내는 데이터는 e.data 에 들어있다.
어떤 에러가 발생할지 모른다면
명확하게 하나의 에러가 아니라, 다양한 에러가 발생할 수 있다면, 타입을 명확하게 체크해주는 것이 좋다.
try {
...
readUser() // 잠재적 에러 발생처
...
} catch (err) {
if (err instanceof ValidationError) {
// validation 에러 처리
} else if (err instanceof SyntaxError) {
// 문법 에러 처리
} else {
throw err; // 알 수 없는 에러는 다시 던지기 함
}
}
스크립트 전역의 에러 잡기
윈도우 전역에서 핸들링되지 않은 에러를 잡을 수 있다.
만능은 아니지만, 이런용도를 통해 개발자에게 에러를 전달하는 목적이있다.
window.onerror = function(message, url, line, col, error) {
alert(`${message}\n At ${line}:${col} of ${url}`);
};
커스텀 에러만들기
에러는 개발자에게 도움을 주기위한 것이기 때문에, 직관적일 수록 좋다.
그래서 커스텀에러를 만들곤 하는데, 이때 Error 를 상속받아 만드는 것이 좋다.
이렇게 했을때 instaceof Error 를 사용할 수 있어, 여러 에러객체를 식별할 수 있다는 장점이 있다.
아래처럼 super에 message 전달을 해준 후 name 프로퍼티를 덮어쓰거나, 새로운 프로퍼티를 추가하면 된다.
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); // 각 행 번호가 있는 중첩된 호출들의 목록
}
에러 객체를 식별할 때, instanceof 도 되지만, name으로 식별할 수 도있다.
// ...
// (err instanceof SyntaxError) 대신 사용 가능
} else if (err.name == "SyntaxError") { // (*)
// ...
'Archive' 카테고리의 다른 글
제너레이터 (0) | 2022.09.04 |
---|---|
Promise의 5가지 API (0) | 2022.09.04 |
내장 클래스 확장하기 (0) | 2022.09.03 |
class의 정적 메서드, 정적 프로퍼티 (0) | 2022.09.03 |
클래스 문법 (0) | 2022.09.03 |