EtoC
비동기 일부 요청 실패 문제 : 해결(Promise.allSettled()) 본문
평소 잘 뜨던 학생대쉬보드 페이지가 다른 계정으로 접속하니 유튜브 API를 활용한 요소만 랜더링되고 나머지는 아무것도 뜨지않았다.
코드 정리를 한다고 axios 요청을 하나로 다 묶어버렸는데, 이게 문제가 된거같다.
코드를 확인해보니 확실히 가장 첫번째 fetch 요청이 실패해서 나머지 요청을 실행하지 않는거였다.
신규 회원이 가입했을경우 최근에 본 강의가 없어서 빈값이 들어왔을때 요청이 실패하는거라는 생각이들었고,
각 요청별로 예외처리를 하지않아서 줄줄이 실패하는 듯.
왜 비동기 요청인데 첫번째 요청이 실패하니까 나머지도 호출이 안되나?
- async/await 비동기 코드를 동기코드처럼 작성할수 있어서 자주사용하고 있었는데, 잘 모르고 사용하고있었다.
- await을 사용하면 비동기 작업중 어딘가에서 에러가 발생하면 바로 catch쪽으로 throw되기때문에 다음 코드가 실행되지않는다.
- 그래서 try/catch를 각 요청마다 해야하는데 마감하면서 코드가 지저분해서 내가 다 합쳐버렸더니 이런 문제가 발생했다.
에러핸들링 코드를 추가해서 실행해 보니
받아온 데이터에는 아예 아무것도 뜨지않았고, 여전히 fetch는 실패;;
애초에 받아오는 데이터를 보니 아무것도 안떠서 백엔드 코드를 확인해봤다.
백엔드 코드에 맞게 예외처리를 해도 여전히 같은 문제가떴다.
이유를 모르겠네..이제 진짜 시간이없는데ㅜㅜ
데이터가 있으면 요청이 성공이니까 비동기요청이 일부 실패해도 나머지는 뜨게할 수 있지않을까?로 생각을 전환.
일단 Promise.all은 제외.
Promise.all은 왜 제외?
Promise.all()은 어떤 요청이 실패하면 전체 프로미스가 rejected 상태가 되어 다른 요청의 결과를 받을 수 없다.
즉, 현재와 똑같은 상태!
찾아보니 Promise.allSettled를 사용하면 어딘가에서 요청이 실패해도 나머지 요청의 결과를 받을 수 있다고한다.
이제 실패해도 성공한 프로미스들은 다불러와지는데 이러면 내가 처음에 작성한 코드만큼 길어져서 맘에 안든다.
음 문제해결!
깔끔하게 역할별로 묶어줬다.
이제 발표할 수 있다!
Promise.allSettled()
allSettled 는 ES11에서 도입된 메서드인데, 모든 요청이 병렬적으로(동시에) 실행되지만, 각각의 요청은 독립적으로 처리된다.
Promise.allSettled()의 장점은 독립적으로 실행된다는 점이다.
독립적으로 실행된 요청의 상태는 fullfilled와 rejected로 나뉘고, 각 요청의 상태와 받아온 데이터 또는 에러를 포함한 배열을 반환한다.
이 배열은 성공했는지 실패했는지와 상관없이 모든 요청의 결과를 포함하며, 에러는 격리하여 다른 요청이 주단되지않도록 보장한다.
promise.allSettled는 일부 데이터 요청이 실패헤도, 성공한 데이터는 사용자에게 보여지게 해주기 때문에 좀 더 안전하고
사용자가 페이지에 접속했을때 화면이 다 안나오는것과 하나만 안나오는거.. 이거 크다..
처음 개발 공부를 했을때는 Promise가 더 어렵고 then then 하는게 싫어서 잘 기피하는 경향이 있었는데
Promise로 속도 개선도 해보고 안되는 문제를 해결해보니 상당히 유용한거같다.