2022-01-08

회사에서 어느 웹을 개발하던 도중에 성능 이슈가 좀 있어서

이를 어찌저찌 개선해보려다 친구놈한테 도움을 좀 청했었는데,

이 친구가 아주 기발한 기법을 알려줬다.

export const sleep = async milliseconds => await new Promise(resolve => setTimeout(resolve, milliseconds));

export const execAsync = async (...api) => {
    let count = 0, results = {};
    for (let i = 0; i < api.length; ++i)
        (async () => {
            try {
                results[i] = await api[i]();
            } catch (e) {e;} finally {
                ++count;
            }
        })();
    while (count !== api.length)
        await sleep(10);
    return results;
};

내가 동시에 호출하고 싶은 API 함수들을 인자로 받고

각각이 끝날 때마다 카운팅해서 다 끝날 때까지 기다리는 로직이다.

마치 Java 스레드의 join과 비슷하다.

저 코드에서 의문이 몇 가지 들 수 있는데,

일단 for 문에서 API를 호출하는 부분을 async-await로 된 즉시 실행 함수로 감싼 이유는

인자로 받는 API 함수 각각이 이미 Promise를 리턴하는 것으로 전제로 하였고,

카운팅은 동기식 코드라 API 호출 후에 카운팅이 되어야하기 때문이다.

그리고 마지막에 while 문으로 모든 API 호출이 카운팅될 때까지 기다리는 데,

sleep 함수를 호출하지 않으면 이 while 문은 동기식 코드가 된다.