다운로드 로직을 작성하고 있었다. 요구사항은 다음과 같았다.
1. 다운로드중 임을 나타내라.
2. 다운로드가 완료되면 알림을 띄워라.
3. 다운로드에 실패하면 실패알림을 띄워라.
4. 다운로드 취소 버튼을 추가하여, 다운로드 중단을 가능하게 해라.
1 - 3 은 비동기 동작과 try catch로 자주 사용한 방식이다.
download()
const download = async () => {
try {
openAlert(1, '다운로드 중입니다.')
await api.post( ... ) // 다운로드 api 요청
closeAlert(1)
openAlert(2, '다운로드가 완료되었습니다.')
} catch(e) {
openAlert(3, '다운로드가 실패했습니다.')
}
}
그런데, 4의 요구사항은 api의 response가 도착하기 전에 네트워크 연결을 끊어야하는 것이다. 지금까지 이러한 요구사항을 처리해본 적이 없기 때문에, 정리하면서 방법을 찾아보려한다.
let controller;
const url = "video.mp4";
const downloadBtn = document.querySelector('.download');
const abortBtn = document.querySelector('.abort');
downloadBtn.addEventListener('click', fetchVideo);
abortBtn.addEventListener('click', function() {
// 4. controller의 abort함수를 실행시키면, fetch요청이 중단된다.
if (controller) controller.abort();
console.log('Download aborted');
});
function fetchVideo() {
// 1. abortController를 생성한다.
controller = new AbortController();
// 2. controller의 시그널을 추출(?)한다.
const signal = controller.signal;
// 3. fetch에 signal을 연결한다.
fetch(url, { signal })
.then(function(response) {
console.log('Download complete', response);
})
.catch(function(e) {
console.log('Download error: ' + e.message);
});
}
공식문서
axios도 마찬가지로 AbortController를 생성하여 signal을 연결하면 된다.
// 1. controller 생성
const controller = new AbortController();
// 2. axios에 signal 연결
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// 3. 중지
controller.abort()
AbortController는 axios 버전 0.22.0
이상부터 지원한다.
하지만 현재 나의 axios 버전은 0.19.x
이기 때문에, 위의 방식이 정상동작하지 않는다.
따라서 axios 버전을 업데이트하거나, cancelToken을 사용해야한다.
cancelToken방식을 사용해보자.
// cancel token 생성
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.post('/user/12345', {
name: 'new name'
}, {
// cancel token 설정
cancelToken: source.token
})
// cancel token과 연결된 호출 취소
source.cancel('Operation canceled by the user.');