(TIL) 예외처리 throw, try, catch, finally

13274 단어 TILTIL

예외처리란

코드 실행의 흐름상 오류가 발생할걸 미리 예상해 오류를 그대로 내보내거나 비정상적인 종료를 막기위해 대비하는것

try {
// 로직이 작성되는곳 여기서 에러가 날 경우 catch로 이동
  const a = "안녕"  
  const a = "나도 안녕" // 여기서 에러가 발생
}
catch {
  console.log("나도 안녕") 
  // 두번째 a에서 에러가 나고 catch로 이동후 콘솔이 찍히고 종료
}
finally{
  console.log("마지막 안녕") 
  // finally는 마지막에 무조건 실행이되는 구문이다.
}
  • try
    로직이 작성되는 곳 이며 예외발생이 가능하다고 생각하는 로직을 try로 감싼다.
  • catch
    에러 핸들링을 해줄수있는 구문이며 try에서 에러가 발생시 catch안으로 오게되고 에러 대비를 위한 코드가 작성된다.
  • finally
    에러가 발생을 하든 안하든 마지막에 무조건 실행되는 부분

throw

에러가 날것을 미리 예상해 catch로 에러를 던저준다.
자신이 속한 try 바깥쪽에 있는 catch로 이동

getProducts: (req, res)=>{
   try {
      if(!req.body.product_id){
        throw new Error("product_id 없다.")
        throw "product_id 없다."
        throw ({message: "product_id 없다."})
        //등등 여러가지 방식으로 사용할수 있다.
      }
   }
   catch (e){
      console.log(e.message) // product_id 없다. 출력
   }
}

catch 안에서도 throw를 사용해서 더 바깥쪽 catch로 이동 가능

getProducts: (req, res)=>{
   try {
      try {
        throw new Error("첫번째 에러")
      }
      catch (e){
        console.log(e.message) // 첫번째 에러
      	throw new Error("두번째 에러")
   }
   catch (e){
      console.log(e.message) // 두번째 에러
   }
}

비동기 방식의 에러처리

나를 엄청 힘들게한 비동기 방식의 에러처리에 대해서 한번 보겠다.
비동기 방식에서는 then과 catch로 콜백을 받아서 결과물이 성공적일 경우에 then으로 에러가 날경우 catch로 받을수 있다.

getProducts: (req, res)=>{
   try {
   	  db.쿼리({})
        .then(result=> {
      	return res.status(200).json({
          result: result
          message: "SUCCESS"
        })
      })
     	.catch(err=> {
        throw new Error("DB_ERROR")
      })
   }
   catch (e){
      return res.status(400).json({
          message: e.message
        })
   }
}

제일 바깥 catch에서 요청 실패에 관한 response를 한번에 처리하려고 비동기 catch에서 throw를 할경우에 바깥 catch를 못찾고 에러가 나는것

에러 이유

비동기 코드의 경우
1. 스택에 올라가고 백그라운드로 이동
2. 백그라운드에서 작업이 완료 콜백큐에서 대기상태
3. 에러 발생시 Js엔진은 스택을 되감고 try, catch를 찾음
4. 하지만 비동기 코드는 스택의 작업물이 다 완료 되고 콜백큐에서 스택으로 올라가기 때문에 이미 스택에는 아무것도 없는상태
5. throw로 던져도 잡을수있는 catch가 없어 에러 발생

그래서 방법은

getProducts: async(req, res)=>{
   try {
   	  await db.쿼리({})
        .then(result=> {
      	return res.status(200).json({
          result: result
          message: "SUCCESS"
        })
      })
     	.catch(err=> {
        throw new Error("DB_ERROR")
      })
   }
   catch (e){
      return res.status(400).json({
          message: e.message
        })
   }
}

이렇게 함수에 async를 붙여주고 비동기 코드에 await을 붙여주면 then, catch에서 throw를 던져도 잘 동작한다.

좋은 웹페이지 즐겨찾기