Generator는 ES6에 새롭게 도입된 개념이다. Generator는 함수이지만 함수와 다른 작동방식을 가지고 있다. 사실 JavaScript만을 따로 공부할 땐 들어본적이 없었는데 redux-saga를 배우면서 알게된 개념이라 한번 정리하고 넘어가는게 좋겠다고 생각했다 !
일반 함수는 하나의 값(혹은 0개의 값)만을 반환합니다.
하지만 Generator를 사용하면 여러 개의 값을 필요에 따라 하나씩 반환 (yield) 할 수 있다.
function* gen() {
yield 1;
yield 2;
yield 3;
}
var g = gen(); // "Generator { }"
Generator는 function*
를 통해 정의된 Generator 함수를 호출하면 만들어지는 객체를 의미한다. 이러게 만들어진 객체는 Iterable이면서 Iterator 이기도 하다. 즉 Generator는 Iterator를 발생시키는 함수인 셈이다.
⚡
Iteralbe : 반복 가능한
Iterator : 반복자
코드
function* gen() {
yield 1;
yield 2;
yield 3;
}
let genn = gen(); // "Generator { }"
for(item of genn) console.log(item);
이 코드를 실행시키게 되면
결과
1
2
3
이렇게 배열들의 모든 요소를 출력 한 것 처럼 yield 옆의 표현식이 출력되었다.
이것이 의미하는 것은 yield 키워드가 Iterable의 요소가 된 것이다. 마치 배열처럼 yield 옆의 표현식이 배열의 요소가 되는 것이라고 생각이 가능하다 (실제 배열이 되는 것은 아니다)
코드
function* gen() {
yield 1;
yield 2;
yield 3;
return 100;
}
let genn = gen(); // "Generator { }"
console.log(genn.next());
console.log(genn.next());
console.log(genn.next());
console.log(genn.next());
yield 이외에 return에도 값을 설정해주고 앞에서 for문을 이용해서 출력했던것을 따르지 않고 Generator는 Iterator이기 때문에 next() 함수를 이용해서 값을 출력할 수 있으므로 사용했다. 이 코드를 실행시키게 되면
결과
{value: 1, done: false}
{value: 2, done: false}
{value: 3, done: false}
{value: 100, done: true}
결과를 살펴보면 yield를 통해 선언된 값들이 전부 출력되고 나서 return값이 출력되고 done: true
로 바뀐 것을 확인할 수 있다.
start -> genn.next() -> yield 1 -> genn.next() -> yield 2 -> ... -> end
Generator에 대한 개념을 찾아보고 예제들을 보고 가장 먼저 든 생각은 바로..
"그래서 Generator를.. 쓰는 이유가 뭔데...?😒"
function infinity() {
let i = 0;
while(true){
return ++i;
}
}
console.log(infinity()); // 1 출력
console.log(infinity()); // 1 출력
console.log(infinity()); // 1 출력
무한 루프를 통해 i값을 증가시키는 함수를 생성하고 출력하기 위해 console.log
안에 넣으면 호출 할때마다 0에서 1만큼 증가한 1값만 계속해서 출력될 것이다.
만약 이를 Generator로 구현하게 되면 어떻게 될까?
function* infinity() {
let i = 0;
while(true){
yield ++i;
}
}
// Generator 객체 생성
const gen = infinity();
console.log(gen.next().value); // 1 출력
console.log(gen.next().value); // 2 출력
console.log(gen.next().value); // 3 출력
원했던 대로 정상적으로 출력되는 것을 확인할 수 있다. 우리가 원할때 gen을 공유한다면 언제 사용하던지 +1
이 된 값을 받아서 사용이 가능하다는 장점이 있다. 또한 yield라는 중단점 때문에 무한루프에 빠지지 않는다.
Generator 함수 내부에서 yield까지만 실행되는 원리를 이용하여 비동기 함수들을 순차적으로 실행이 가능하다.
하지만 이 방식은 잘 사용하진 않는다.. 왜냐하면.. async/await을 이용한 코드가 가독성이 좋기 때문에..
redux-saga를 다루기 위해 Generator에 대한 간단한 설명을 살펴보았는데.. 솔직히 왜 쓰는지 확 와닿지가 않아서 redux-saga에 대해 다룰때 느낄수 있길.. 🙏