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

 

 

 

Posted by bloodguy

댓글을 달아 주세요