똑같은 삽질은 2번 하지 말자
setInterval 안에서 비동기 처리를 넣었는데 순서보장이 안될 때 해결하기 본문
개요
setInterval 안에 processing 이라는 파일 업로드의 진행을 파악하기 위한 API를 넣었는데 순서대로 되지 않고 processing이 뒤죽박죽이 됬을때 해결하는 방법
setTimeout을 쓰면된다
setTimeout은 한번밖에? 실행안되지 않나? 라고 생각했지만, 재귀호출을 통해 반복적으로 호출하는 동작을 구현하면 된다.
예를 들면 setInterval로 구현한 형태가 밑과 같다면
const startProgress = setInterval(async () => {
await getProgress();
}, 1000)
onUnmouted(() => clearInterval(startProgress))
이를 이렇게 바꿔주면 된다.
let timeout;
const startProgress = () => {
timeout = setTimeout(async () => {
await getProgress();
startProgress();
}, 1000);
};
onMounted(() => startProgress())
onUnmouted(() => if (timeout) clearTimeout(timeout))
근데 setInterval 안에서 비동기로직을 실행할 때 왜? 순서가 보장되지 않을까?
setInterval은 내가 1000이라고 넣었던 숫자에 의존해서 1000ms 마다 무조건 콜백함수를 실행시킨다.
즉, 콜백함수가 비동기 함수여서 아직 처리가 끝나지 않았다 해도 다른 비동기 처리를 실행시켜 버리는 것이다.
그에 비해 setTimeout을 보면 재귀호출을 할 때 async await를 통해 비동기 처리를 기다리고 난 뒤, 재귀호출이 이루어짐으로써 순서를 보장할 수 있게 된다.
또 setInterval 을 잘못써서 axios timeout이 계속 발생했었는데, "정확히 이게 원인이라서 타임아웃이 일어난다" 라는 정답을 결국 못찾았지만 추측한건, setInterval로 인해 복수의 비동기처리가 pending 되어 있는 상태이다. 그 상태에서 clearInterval을 실행시키고 다른 동기처리를 실행하는데 동기처리의 시간이 30초 이상이 되버리자 pending 되어 있던 비동기처리를 axios에서 timeout으로 처리를 해버리는 것이다. 라고 쓰고 있지만, 이건 아닌거 같기도 하고 나중에 좀 더 시야가 트이게 되면 다시 수정하자 나님아