[JavaScript] fetch 실행 중 중단 (사용자입력, 타임아웃) (abort/stop fetch signal/timeout)
JavaScript 2022. 5. 19. 17:48
fetch()를 통한 요청 중 오래 걸리는 요청일 경우 '중단'버튼 클릭이나 timeout을 두고 중단이 필요한 경우가 있을 수 있음.
이럴 때 AbortController를 이용해 처리가 가능.
먼저 사용자 버튼클릭 이벤트로 중단하는 방법.
// <button id="btn_abort">중단</button> 이란 엘리먼트가 있다고 가정함
/**
* fetch(url), signal이 있을 경우 중단
* @param {string} url 요청할 url
* @param {AbortSignal} signal 중단 시그널
* @return {Promise} Response
* @throws {DOMException}
*/
function fetchAbortable(url, signal)
{
return new Promise(async(resolved, rejected)=>{
let r = null;
try {
r = await fetch(url, {signal: signal});
} catch (e) {
return rejected(e);
}
return resolved(r);
});
}
const controller = new AbortController();
// 사용자가 버튼 클릭시 중단
document.querySelector('#btn_abort').addEventListener('click', () => controller.abort());
let r = null;
try {
// 10초 이내에 사용자 버튼 클릭시 중단, 그 이상일 경우엔 성공적으로 응답 가져옴
r = await fetchAbortable('https://httpstat.us/200?sleep=10000', controller.signal);
} catch (e) {
console.log(e);
}
console.log(r);
timeout은 이렇게.
/**
* fetch(url) with timeout
* @param {string} url 요청할 url
* @param {number} timeoutMs timeout
* @return {Promise} Response
* @throws {DOMException}
*/
function fetchTimeout(url, timeoutMs)
{
const controller = new AbortController();
const promise = fetch(url, {signal: controller.signal});
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
return promise.finally(() => clearTimeout(timeoutId));
}
// 성공
r = await fetchTimeout('https://httpstat.us/200?sleep=1000', 3000);
// 실패 (Uncaught DOMException: The user aborted a request.)
r = await fetchTimeout('https://httpstat.us/200?sleep=3000', 1000);
[참고]
https://developer.mozilla.org/en-US/docs/Web/API/AbortController