try-catch-finally
try
블럭에서 에러가 나면catch
에서 받아서 처리한다.
finally
는 try문이 성공하던 실패하던 마지막에 반드시 실행해야하는 코드를 명시한다.
사용 팁
throw
는 어떤 객체든 수용하지만,Error 오브젝트
를 전달하자 ( 스택 트레이스 짱짱 )
throw new Error('최대한 상세하게 상황을 명시하자');
try-catch
문은 정말 에러가 발생할 수 있는 코드만 감싸는 것이 코드파악하기 더 좋다.
- 에러를 유의미하게 처리할 수 있는 부분에서
catch
하자.
무조건 원인이 발생하는 부분에서 바로 catch를 해야하는 것은 아니다.
에러를 받고도 별다른 유의미한 행위를 할 수 없다면, 상위단계에서 catch하는 것이 좋다.
- 커스텀 에러 클래스 만들어서 쓰자 (
extends Error
)
코드 예시 1) - finally
어차피 순차실행인데 굳이
finally
를 쓰는 이유가 뭘까? 싶으면 아래를 보자.- catch문에서 리턴하는 경우
리턴하면 코드흐름이 다른곳으로 이동하므로
파일닫기()
코드는 실행되지 않는다.// Bad ... try{ 파일읽기(); } catch(error){ console.log("파일 읽기 실패"); return; } 파일닫기(); // catch문에 리턴이 있으므로, 에러가 발생한다면 이 코드는 실행되지 않는다.
// Good ! try{ 파일읽기(); } catch(error){ console.log("파일 읽기 실패"); return; } finally { // finally로 감싸면 try문이 성공하던 실패하던 파일닫기() 함수가 호출된다. 파일닫기(); }
코드예시 2) - 커스텀 에러 정의
타입스크립트의 구현상 한계로
Error
확장해서 instance of
로 에러 구분하던 방식이 그냥은 안된다.대안
생성자함수
에서super()
호출 직후, 프로토타입을 명시적으로 설정하면instance of
를 쓸 수 있다.
- 이 방식은 익스플로러 10 이하는 지원이 안된다는 단점이 있음.
setPrototypeOf
를 쓰려면tsconfig.json
에서lib
compiler option을 "es2015
" 이후로 설정.
// tsconfig.json { "compilerOptions": { "lib": ["es2015", "DOM"] } }
class FooError extends Error { constructor(m: string) { super(m); // Set the prototype explicitly. Object.setPrototypeOf(this, FooError.prototype); // <--- 이거 추가! } sayHello() { return "hello " + this.message; } } const error = new FooError("msg"); if (error instanceof FooError) { console.log(error.sayHello()); }
instance of 처리문 예시
try { // 에러가 날 수 있는 행위 수행 ... } catch (e) { if (e instanceof NetworkError) { // 블라블라 처리.. } else if (e instanceof RangeError) { // 블라블라 처리.. } }