본문 바로가기
Frontend/Javascript

비동기 에러처리 🤔

by 우보틀 2022. 6. 1.

문득 setTimeout에 전달된 함수는 어떻게 에러처리를 해야하난 궁금해져서 이 문서를 작성합니다.

 

살펴볼 예시는 4가지 입니다.

  • try/catch
  • setTimeout with try/catch
  • Promise의 catch
  • async/await with try/catch

 


try/catch

 

try/catch는 예외상황을 다뤄야 할때 주로 사용합니다.

javascript가 런타임에서 에러가 나면 이후의 코드는 실행되지 않고 멈추어 버리기 때문에 예외처리는 중요합니다.

예외가 발생할 수 있는 곳에 보험을 들어서 이후의 동작을 수행할 수 있도록 하는 것이 중요하다고 생각합니다.

 

아래의 코드가 있습니다.

하나는 try/catch로 감싼것, 감싸지 않은 것입니다.

감싸지 않은 것에서는 에러가 발생하여 이후의 동작을 하지 않는 것을 볼 수 있습니다.

런타임에서 아래와 같은 상황이 발생하면 사용자는 불편함을 겪을 것입니다.

 

아래의 코드는 try/catch로 에러를 감싸주었고 이후의 코드가 실행되는 모습을 볼 수 있습니다.

 


setTimeout with try/catch

 

setTimeout과 같은 비동기 동작에서 try/catch를 사용하려면 어떻게 해야 할까요???

아래의 코드는 제가 의도한 대로 동작이 될까요?

try {
    setTimeout(() => {
        throw new Error('hihi')
        console.log('byebye')
    }, 500)
} catch(e) {
    console.log(e)
}

정답은 동작하지 않습니다.

 

태스크 큐에 존재하던 setTimeout의 콜백함수가 새로이 실행컨텍스트를 생성하여 실행이 되기 때문에 우리가 원하는대로 동작하지 않을까 싶습니다.

콜백함수 자체를 try/catch로 감싸주면 우리가 원하는대로 동작이 수행될 것입니다.

위의 사진은 우리가 원하는대로 에러를 catch하고 이후의 동작을 수행해 줍니다.

 


promise의 catch

 

비동기 동작을 지원해주는 promise에서는 catch를 이용하여 에러를 처리해줄 수 있습니다.

아래의 코드에서는 resolve를 통해 then을 실행시켜주었습니다.
then 내부에서 error를 반환하여 catch에서 처리해 줄 수 있도록 하였습니다.

아래와 같이 reject를 반환하여 바로 catch에서 에러 처리를 할 수 도 있습니다.

 


async/await with try/catch

 

es2017에서 등장한 async/await 입니다.

promise의 then chaining은 방대해지는 경우 코드의 가독성을 떨어뜨렸습니다.

이러한 점을 반영하여 async/awiat이 등장합니다.

 

promise -> generator -> async/await의 흐름으로 진행이 됩니다. 

generator에 대한 내용은 나중에 언급하겠습니다.

next와 yield를 통해 함수의 실행을 정지 시킬 수 있다가 핵심입니다.

 

async/await은 try/catch로 감싸주어 에러 처리를 할 수 있습니다.

a = () => new Promise((resolve, reject) => {
  reject('hihi')
})

(async () => {
    try {
        await a()
    } catch(e) {
        console.log(e)
    }
    console.log('byebye')
})()

아래는 실행된 모습입니다. 

await에서 발생한 에러를 try/catch문에서 처리해주고 이후의 동작을 수행하는 것을 볼 수 있습니다.

 

 

비동기 에러 처리 관련 질문을 받았을때 제대로 답변하지 못해 이렇게 정리하여 포스팅을 합니다.