generator
- 함수 실행 중지와 실행 재개가 컨트롤이 가능한 함수
- function으로 구현하며 함수명 앞에 *이 붙는다.
- return이 아닌 yield로 값을 반환한다.(중단점 + 값 반환 역할)
- next()를 호출하면 yield 앞까지의 값이 반환된다.
- next()의 반환값은 {value: 반환값, done: 제너레이터 함수 끝까지 실행여부}
function * counter() {
yield 1
yield 2
yield 3
}
const g = counter();
console.log(g.next()); // {value: 1, done: false}
console.log(g.next()); // {value: 2, done: false}
console.log(g.next()); // {value: 3, done: false}
console.log(g.next()); // {value: undefined, done: true}
yeild를 활용한 무한루프
- true로 while을 돌려도 yield라는 중단점때문에 무한루프에 빠지지 않음
function* genAddNum() {
let i = 0;
while(true) {
yield ++i;
}
}
const gen = genAddNum();
gen.next(); // {value: 1, done: false}
gen.next(); // {value: 2, done: false}
gen.next(); // {value: 3, done: false}
// ... 무한 실행 가능
피보나치 수열 구현
function fnFibonacci(_num){
function * genFibonacci(_num) {
let a = 0;
let b = 1;
while(true){
let c = a;
a = b;
b = c + a;
// 위의 3줄을 1줄로 표현하면 [a, b] = [b, a+b];
yield a
}
}
const fib = genFibonacci();
const arr = [];
for(const num of fib) {
if(num > _num) break;
arr.push(num)
}
return arr;
}
console.log(fnFibonacci(50));
generator 활용한 비동기 처리
- 제너레이터 함수 내부에서 yield까지만 실행되는 원리를 이용해서 비동기를 순차적으로 실행가능
const fs = require('fs')
function * gen() {
const a = yield read_gen(g, 'a.txt')
console.log(a)
const b = yield read_gen(g, 'b.txt')
console.log(b)
const c = yield read_gen(g, 'c.txt')
console.log(c)
}
// 비동기 처리 완료를 기다리고, 다음 함수를 연속해서 호출하는 함수
function read_gen (_g, fname) {
fs.readFile(fname, 'utf-8', (err, data) => {
_g.next(data)
})
}
const g = gen();
read_gen (gen(), '');
async/await와 비교
function read_promise(fname) {
return new Promise((resolve, reject) => {
fs.readFile(fname, 'utf-8', (err, data) => {
resolve(data);
});
});
}
(async function readAll () {
const a = await read_promise('a.txt');
console.log(a);
const b = await read_promise('b.txt');
console.log(b);
const c = await read_promise('c.txt');
console.log(c);
})();