본문 바로가기
클린코드 샘플(JavaScript)

비동기 처리에 대한 클린 코드 예제

by 찬찬2 2022. 11. 21.

 

<body>

    <select name="" id="selector">
        <option value="" disabled selected></option>
        <option value="5">5</option>
        <option value="6">6</option>
        <option value="7">7</option>
        <option value="8">8</option>
    </select>

    <div id="result">id를 선택하세요.</div>

    <script>

    document.querySelector("#selector").addEventListener("change", handleChange);

    /* default */
    function renderProduct(product){
        const resultElem = document.querySelector("#result");
        resultElem.replaceChildren();
        resultElem.insertAdjacentHTML(
            "beforeend",
            `
            <p>${product.title}</p>
            <p>${product.price}</p>
            <p>${product.description}</p>
            <p><img src='${product.images[0]}' style='width: 300px'></p>
            `
        );
    }

    /* main */
    async function getProduct(id){
        const res = await fetch(`https://api.escuelajs.co/api/v1/products/${id}`);
        const json = await res.json();
        return json;
    }

    async function handleChange(e){
        const id = e.target.value;
        const product = await getProduct(id);
        renderProduct(product);
    }

    </script>
</body>

 

■ 흐름

select event → handleChange → getProduct → renderProduct → render

 

※ 1차 리팩토링 - getProduct 함수에서 fetch를 분리한다.

getProduct 함수는 이제 fetchProduct 함수의 결과 값만 출력해주는 기능을 수행하게되었고 더이상 async/await가 필요하지 않게 되었다. (사용해도 기능이 작동하는데 영향을 주지 않는다)

 

async function fetchProduct(id){
    const res = await fetch(`https://api.escuelajs.co/api/v1/products/${id}`);
    const json = await res.json();
    return json;
}

function getProduct(id){
    const json = fetchProduct(id);
    return json;
}

 

※ 2차 리팩토링 - 범용성을 고려한 추가적인 분리 그리고 화살표함수 이용

화살표 함수를 이용해 코드블럭과 return 키워드를 제거해 가독성이 보다 더 올라갔다. 그리고 async/await를 사용하지 않은 것을 볼 수 있다.

 

const fetchJson = url => fetch(url).then(res => res.json());

const fetchProduct = id => fetchJson(`https://api.escuelajs.co/api/v1/products/${id}`);

const getProduct = id => fetchProduct(id);

async function handleChange(e){
    const id = e.target.value;
    const product = await getProduct(id);
    renderProduct(product);
}

 

■ 흐름

select event → handleChange → getProduct → renderProduct → render

 

■ async/await를 마구 써도 괜찮은가?

promise를 여러번 감싼다고 해서 microTaskQueue가 감당을 못하는 것은 아니기 때문에 성능저하를 일으킬 경우는 드물다고 한다. 하지만 위와 같은 중간 단계의 함수에서도 async/await를 사용하게 된다면 비동기 제어가 필요한 것이 아님에도 async/await를 표기했다는 것 자체로 협업하는 팀원들 사이에서는 "반드시 비동기 처리를 동기적으로 마친 후에야 다음 코드로 진행해야 한다"는 오해를 불러일으킬 가능성이 크다.

 

참고링크

댓글