ES6 Generator 예제

Apr 10, 2017

Generator는 빠져나갔다가 나중에 다시 돌아올 수 있는 함수다.

파일 업로드 처리하는데, 동시에 처리하는 파일의 개수를 제한할 필요가 있었다. while과 setInterval 조합으로 처리하려다가 좀 더 세련되고, 최근 기술을 사용하고 싶어서 Generator를 사용했다.

1번 예제는 써도 괜찮지만 2번 예제는 보완이 필요해 보인다.

비동기 함수를 순차적으로 실행하는 예제

다음은 Generator를 사용해서 비동기 함수를 순차적으로 실행하는 간단한 코드다.

// 실행하려는 비동기 함수
function PromiseFunc(i) {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log('returned', i)
            resolve();
        }, 1000);
    });
}

// 이터레이터를 만드는 함수. *과 yield 사용
function* getIterator() {
    for (let i=0; i<10; i++) {
        yield PromiseFunc(i);
    }
}

// 이터레이터를 가져온다.
const it = getIterator();
(function nextItem(val) {
    // ret = {value: ..., done: true or false}
    let ret = it.next(val);

    // 이터레이터의 다음이 있는지?
    if(!ret.done) {
        ret.value.then(nextItem);
    } else {
        console.log("finished");
    }
})()

동시에 10개씩 처리하는 예제

이번에는 10개씩 동시 처리하는 예제다.

// 실행하려는 비동기 함수
function PromiseFunc(i) {
    return new Promise((resolve) => {
        console.log('invoked', i)

        // 비동기 처리
        setTimeout(() => {
            console.log('returned', i)
            resolve(i);
        }, 1000);
    });
}

// 이터레이터를 만드는 함수. *과 yield 사용
function* getIterator() {
    for (let i=0; i<100; i++) {
        yield PromiseFunc(i);
    }
}

// 이터레이터를 가져온다.
const it = getIterator();

// 동시에 처리할 개수 지정
const CONCURRENT = 10;

// 카운트 초기화
let cnt = 0;

// 처리 시작
(function nextItem() {
    let ret = it.next();

    // 카운트 증가
    cnt++;

    if(!ret.done) {
        ret.value.then(() => {
            // 처리가 완료되어 카운트 감소
            cnt--;
        });

        let timer = setInterval(() => {
            if(cnt < CONCURRENT) {
                nextItem();
                clearInterval(timer);
            }
        }, 0);
    } else {
        console.log("finished");
    }
})()
See Also