Axios의 요청 config에는 onUploadProgress와 onDownloadProgress 설정이 있다.
// `onUploadProgress`는 업로드 진행 이벤트를 처리합니다.
// 브라우저 전용
onUploadProgress: function (progressEvent) {
// 업로드 진행 이벤트 작업 수행
},
// `onDownloadProgress`는 다운로드로드 진행 이벤트를 처리합니다.
// 브라우저 전용
onDownloadProgress: function (progressEvent) {
// 다운로드 진행 이벤트 작업 수행
}
업로드와 다운로드에 대한 요청 진행 상황을 나타내는 progressEvent 객체를 이용한다.
ProgressEvent HTTP 요청과 같이 기본 프로세스의 진행률을 측정하는 이벤트이다.
ProgressEvent.lengthComputable
전송된 데이터의 크기을 계산할 수 있는지에 대한 boolean값
ProgressEvent.loaded
이미 전송, 처리된 데이터의 크기를 나타내는 64비트 정수
ProgressEvent.total
전송되거나 처리되는 데이터의 총 크기
http를 사용하여 리소스 다운할때 이 값은 Content-Length 응답 헤더에서 가져온다.
요청이 then 또는 catch로 처리되기 전에 요청과 응답을 가로챕니다.
// 요청 인터셉터 추가하기
axios.interceptors.request.use(function (config) {
// 요청이 전달되기 전에 작업 수행
return config;
}, function (error) {
// 요청 오류가 있는 작업 수행
return Promise.reject(error);
});
// 응답 인터셉터 추가하기
axios.interceptors.response.use(function (response) {
// 2xx 범위에 있는 상태 코드는 이 함수를 트리거 합니다.
// 응답 데이터가 있는 작업 수행
return response;
}, function (error) {
// 2xx 외의 범위에 있는 상태 코드는 이 함수를 트리거 합니다.
// 응답 오류가 있는 작업 수행
return Promise.reject(error);
});
const requestInterceptor = axios.interceptors.request.use(function (config) {
config.metadata = { startTime: new Date() }
return config;
}, (error) => {
return Promise.reject(error)
})
const responseInterceptor = axios.interceptors.response.use(function (response) {
response.config.metadata.endTime = new Date();
response.duration = response.config.metadata.endTime - response.config.metadta.startTime;
return response;
}, (error) => {
error.config.metadata.endTime = new Date();
error.duration = error.config.metadata.endTime - error.config.metadata.startTime;
return Promise.reject(error);
})
axios.interceptors.request.eject(requestInterceptor)
axios.interceptors.response.eject(responseInterceptor)
클라이언트에서 서버로 요청을 보내고 응답까지 오는 과정을 progress 로 나타내고 싶다.
하지만 axios의 config인 onUploadProgress와 onDownloadProgress는 서버로 요청을 보내는데 완료되는 과정을 표현한다.
나는 api 통신 상태를 Progress Percentage로 나타나게 하기 위해 아래 코드 처럼 작성하였다.
const fetchTestAPI = async () => {
setInprogressDataLoading(true);
setShowPercent(true);
try {
intervalRef.current = setInterval(() => {
setProgress(prev => {
if (prev < 99) {
return prev + 1;
} else {
clearInterval(intervalRef.current);
return prev;
}
});
}, 100);
const response = await axios.post('/test', {
onDownloadProgress: (progress) => {
const { loaded, total } = progress;
if (total) {
const percent = Math.floor((loaded * 100) / total);
setProgress(percent);
}
}
});
if (response) {
setProgress(100);
clearInterval(intervalRef.current);
}
} catch (e) {
console.error(e);
} finally {
setTimeout(() => {
setInprogressDataLoading(false);
setProgress(0);
}, 400);
clearInterval(intervalRef.current);
}
}
한마디로 응답 받기 전까지 전송이 완료 되었다면 percentage를 100ms 당 1씩 증가해 99까지 올리고 응답을 받았으면 100으로 변경하는 방식으로 api 로딩 progress를 표현하였다.
이 코드도 100%가 되어도 응답을 받지 못한다면 progress bar가 표현되는 문제도 있지만 이를 통해서 onDownloadProgress와 onUploadProgress를 통해 http 요청 시 Content가 얼마 만큼 전송 되었는지 알 수 있는 config를 배우게 되었다.