• 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();