Generator는 빠져나갔다가 나중에 다시 돌아올 수 있는 함수다.
파일 업로드 처리 하는데, 동시에 처리하는 파일의 갯수를 제한할 필요가 있었다. while과 setInterval 조합으로 처리하려다가 좀 더 세련되고, 최근 기술을 사용하고 싶어서 Generator를 사용했다.
1번 예제는 써도 괜찮지만 2번 예제는 보완이 필요해 보인다.
비동기 함수를 순차적으로 실행하는 예제
다음은 Generator를 사용해서 비동기 함수를 순차적으로 실행하는 간단한 코드다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// 실행하려는 비동기 함수 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개씩 동시 처리하는 예제다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
// 실행하려는 비동기 함수 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"); } })() |