axios의 onUploadProgress, onDownloadProgress에 대하여

세니·2024년 6월 12일
1
post-thumbnail

Axios onUploadProgress, onDownloadProgress

Axios의 요청 config에는 onUploadProgress와 onDownloadProgress 설정이 있다.

// `onUploadProgress`는 업로드 진행 이벤트를 처리합니다. 
// 브라우저 전용 
onUploadProgress: function (progressEvent) { 
// 업로드 진행 이벤트 작업 수행 
}, 
// `onDownloadProgress`는 다운로드로드 진행 이벤트를 처리합니다. 
// 브라우저 전용 
onDownloadProgress: function (progressEvent) { 
// 다운로드 진행 이벤트 작업 수행 
}

업로드와 다운로드에 대한 요청 진행 상황을 나타내는 progressEvent 객체를 이용한다.

ProgressEvent

ProgressEvent HTTP 요청과 같이 기본 프로세스의 진행률을 측정하는 이벤트이다.

ProgressEvent.lengthComputable
전송된 데이터의 크기을 계산할 수 있는지에 대한 boolean값

ProgressEvent.loaded
이미 전송, 처리된 데이터의 크기를 나타내는 64비트 정수

ProgressEvent.total
전송되거나 처리되는 데이터의 총 크기
http를 사용하여 리소스 다운할때 이 값은 Content-Length 응답 헤더에서 가져온다.

Axios Intercepters

요청이 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); 
});

axios 요청 응답에 걸리는 시간은

  1. axios interceptor를 이용해서 startTime을 기록한다. -> axios.interceptors.requset
  2. axios.interceptors.response에서 endTime
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를 배우게 되었다.

profile
세니는 무엇을 하고 있을까

0개의 댓글