Error
보통 Java 에서는 Exception Object를 선언하지만 JavaScript 에서는 Error Object 를 선언하여 사용한다. Error Object의 handling은 예상하지 못하는 에러는 Error(Exception)로 던지거나, 예상할 수 있는 에러는 Error(Error State)를 Handling하여 try → carch → finally 형식으로 작성한다.
Exception : exception 은 예상하지 못한 에러가 발생하는 에러를 말한다. (예상하지 못하는 에러)
Error State : error state 는 예상되는 에러가 발생하는 에러를 말한다. (예상할 수 있는 에러)
*// #1 - Error(Exception)*
function readFile(fileName: string): string {
if (fileName === 'not exist!💩') {
throw new Error(`file not exist! ${fileName}`);
}
return 'file contents🗒';
}
*// #2 - Error(Error State)*
function closeFile(fileName: string) {
*// close...*
}
function run() {
const fileName = 'not exist!💩';
try {
console.log(readFile(fileName));
} catch (error) {
console.log(`catched!!`);
return;
} finally {
closeFile(fileName);
console.log(`closed!`);
}
}
run();
try 안에는 정말로 에러가 많이 발생하는 부분만 넣어서 try 안에 작성하는 것이 좋으며, finally 안에는 catch 가 return 이 되더라도 실행 되므로 되도록 catch 다음 실행해야 할 함수들이 있으면 finally 안에 작성하는 것이 좋다.
handling
class TimeoutError extends Error {}
class OfflineError extends Error {}
*// #1*
class NetworkClient {
tryConnect(): void {
*// Error(Exception)*
throw new OfflineError('no network!');
}
}
*// #2*
class UserService {
constructor(private client: NetworkClient) {}
login() {
this.client.tryConnect();
}
}
*// #3*
class App {
constructor(private userService: UserService) {}
run() {
try {
this.userService.login();
} catch (error) {
*// Error(Error State)*
*// show dialog to use*
*// 3개의 클래스에서 try-catch 를 한다면 가능한 여기에서 에러 handling 하는 것이 좋다.
// 이유는 아래 설명 참고..*
}
}
}
const client = new NetworkClient();
const service = new UserService(client);
const app = new App(service);
app.run();
try-catch 를 사용할 때는 에러가 발생 하였을 때 해당 에러에 적절한 핸들링이 가능한 곳에서 try-catch 를 사용해야 한다. 아무 곳에 서나 try-catch 를 사용한다면 에러는 잡히지만, 에러에 맞는 후속 처리가 꼬여버리게 되기 때문이다.
state
type NetworkErrorState = {
result: 'fail';
reason: 'offline' | 'down' | 'timeout';
};
type SuccessState = {
result: 'success';
};
type ResultState = SuccessState | NetworkErrorState;
*// 에러 처리 시 상태에 대해서는 Union 타입을 사용하여 각 에러에 대한 정확한 에러의 종류를*
*// 명시하는 것이 좋다.*
*// #1*
class NetworkClient {
tryConnect(): ResultState {
return {
result: 'success',
};
}
}
*// #2*
class UserService {
constructor(private client: NetworkClient) {}
login() {
this.client.tryConnect();
}
}
*// #3*
class App {
constructor(private userService: UserService) {}
run() {
try {
this.userService.login();
} catch (error) {
*// show dialog to use*
}
}
}
const client = new NetworkClient();
const service = new UserService(client);
const app = new App(service);
app.run();