[메모] fetch with abort

임택·2021년 3월 5일
0

메모

목록 보기
1/14
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>

<body>
    <h1>Fetch test with abort </h1>
    <button id="btn">업데이트</button>
    <main id="root"></main>

    <script type="module">
        const log = console.log;
        const $ = (sel) => document.querySelector(sel);

        const abortableFetch = (name, req, opts) => {
            window.test = window.test || {};
            if (window.test[name])
                window.test[name]();

            const controller = new AbortController();
            const signal = controller.signal;
            const abort = () => {
                console.log('aborted!');
                controller.abort();
            };

            window.test[name] = abort;
            return request(req, { ...opts, signal });
        }
                
        const request = async (url, options) => {
            try {
                const res = await fetch(url, options);
                
                if (res.ok)
                    return { 
                        ...(await res.json()),
                        error: 0
                    };
                else 
                    throw res;
            } catch (res) {
                const data = {};
                if (res.name == 'AbortError') {
                    console.log(">>>>> ", res);
                    data = {
                        status: 500,
                        error: 2,
                    }
                } else {
                    data = { 
                        status: res.status,
                        error: 1,
                    };
                    console.log(res, data);

                }

                
                return data;
            }
        };
        
        const API_ENDPOINT = 'https://oivhcpn8r9.execute-api.ap-northeast-2.amazonaws.com/dev';
        const FATCH = 'FATCH';
        const CAT = 'CAT';
        const RANDOM = 'RANDOM';

        const api = {
            fetchCats: (keyword) => 
                abortableFetch(FATCH, `${API_ENDPOINT}/api/cats/search?q=${keyword}`),
                // request(`${API_ENDPOINT}/api/cats/search?q=${keyword}`),
            getCat: (id) => abortableFetch(CAT, `${API_ENDPOINT}/api/cats/${id}`),
            getRandom: () => abortableFetch(RANDOM, `${API_ENDPOINT}/api/cats/random50`),
            
            // TODO
            fetchGif: (keyword) => abortableFetch(`${API_ENDPOINT}/api/gif/search?q=${keyword}`),
            fetchGifAll: () => abortableFetch(`${API_ENDPOINT}/api/gif/all`),
        };

        const root = $('#root');
        const append = (child, parent) => parent.appendChild(child);

        const templ = data => {
                return data && data.map(({id, url, name}) => (
                    `
                        <div style="width: 200px; display: inline-block; flex: 2">
                            <p>${id}: ${name} </p>
                            <img src='${url}' style="width: 100px;">
                        </div>
                    `
                )).join('')
        };

        let debounce = null;
        $('#btn').addEventListener('click', (e) => {
            if (debounce != null) {
                clearTimeout(debounce);
                log('hello');
            }
            
            debounce = setTimeout(async () => {
                console.log('btn');
                const datas = async () => await api.fetchCats('norway');
                const d = await datas();
                console.log('while', d);
                const div = document.createElement('div');
                div.style = "display: flex; flex-wrap: wrap; transform: translateY(100%); transition: none;"
                div.innerHTML = templ(d.data);        
                root.innerHTML = '';        
                append(div, root);

                setTimeout(() => {
                    div.style = "display: flex; flex-wrap: wrap; transform: translateY(0); transition: transform 2s;"
                }, 1000);
            }, 200);

        });

        
    </script>
</body>
</html>
profile
캬-!

0개의 댓글