본문 바로가기

Frontend/Javascript

[Javascript] Generator

안녕하세요.

오늘은 Generator에 대해서 알아보도록 하겠습니다.

🔸  Generator란?

Generator는 함수의 실행을 중간에 멈췄다가 재개할 수 있는 함수입니다.

이때 컨텍스트는 저장된 상태로 남아 있습니다.

 

예제

Generator 함수는 호출되어도 즉시 실행되지 않고, 함수를 위한 Iterator 객체를 반환합니다.

function* idMaker() {
	let index = 0;
    while (index < 3) {
    	yield index++;
    }
}   
let iter = idMaker();

console.log(iter.next()); //{value: 0, done: false}
console.log(iter.next()); //{value: 1, done: false}
console.log(iter.next()); //{value: 2, done: false}
console.log(iter.next()); //{value: undefined, done: true}

Iterator의 next() 메서드를 호출하면 함수가 실행되어 yield 문을 만날 때까지 진행되고, iterator는 yield문이 반환할 값을 나타내는 value 속성과 마지막 yield문을 실행했는지 여부를 나타내는 done 속성을 리턴합니다.

🔸  메서드

next

yield 표현을 통해 yield 된 값을 반환합니다.

next 메서드에 인수를 전달하여 활용할 수 있습니다.

 

return

주어진 값을 반환하고 generator를 종료합니다.

(done 속성이 true로 세팅됩니다.)

 

throw

error를 throw하고 generator를 종료합니다.

(done 속성이 true로 세팅됩니다.)

🔸  특징

1. iterator 이면서 iterable 합니다.

iterable

- Symbol.iterator 메서드가 있습니다.

- Symbol.iterator는 iterator를 반환해야 합니다.

 

iterator

- next 메서드를 가집니다.

- next 메서드는 value와 done 속성을 가진 객체를 반환합니다.

- 작업이 끝나면 done은 true가 됩니다.

 

2. Lazy evalutaion

미리 값을 만들어두지 않고, 필요할 때 값을 요구하기 때문에 메모리를 효율적으로 사용할 수 있습니다.

function newArr(n) {
  let i = 1;
  const res = [];
  while (i < n) {
    console.log(i); // 1, 2, 3, 4, 5,...99
    res.push(i++);
  }
  return res;
}
function* newArrGen(n) {
  let i = 1;
  while (i < n) {
    console.log(i); // 1, 2, 3, 4, 5,...11
    yield i++;
  }
}
function fiveArr(iter) {
  const res = [];
  for (const item of iter) {
    if (item % 5 == 0) res.push(item);
    else if (res.length == 2) break;
  }
  return res;
}

console.log(fiveArr(newArr(100))); // fiveArr([1, 2, 3, 4... 99, 100]);
console.log(fiveArr(newArrGen(100)));

 newArr는 즉시 배열을 만들어 내기 때문에 fiveArr 함수에 [1, 2, 3,... 99, 100]이 전달됩니다. 반면 newArrGen은 fiveArr 함수에  iterator만 전달합니다.

 

 

3. yield*로 다른 generator를 호출

function* gen1() {
    yield 1;
    yield* gen2();
    yield 4;
}

function* gen2() {
    yield 2;
    yield 3;
}

const iter1 = gen1();

console.log(iter1.next()); //{value: 1, done: false}
console.log(iter1.next()); //{value: 2, done: false}
console.log(iter1.next()); //{value: 3, done: false}
console.log(iter1.next()); //{value: 4, done: false}

//전개 연산자를 사용해서 다음과 같이 호출할 수 있습니다.
console.log(...gen1()) // 1, 2, 3, 4

🔸 활용

- async/await

 async/await은 generator와 promise를 활용하여 구현합니다.

 비동기 처리가 끝나면 yield를 통해 제어권을 넘기고,  비동기 결과로 리턴된 promise의 then에서 재귀적으로 iterater.next를 호출하는 방식으로 구현됩니다.

 

(자세히 https://meetup.toast.com/posts/73)

 

- redux-saga

 

 

오늘은 Generator에 대해서 알아보았는데요, 틀린 것이 있거나 궁금한 것이 있으시면 댓글 부탁드립니다.

감사합니다.

 

 

출처

https://bbaktaeho-95.tistory.com/80

https://meetup.toast.com/posts/73

https://www.youtube.com/watch?v=qi24UqyJLgs

 

'Frontend > Javascript' 카테고리의 다른 글

[Javascript] Prototype 프로토타입  (0) 2022.04.10
[Javascript] Promise  (0) 2022.04.04
[Javascript] Garbage Collection  (0) 2022.03.22
[Javascript] Closure 클로저  (0) 2022.03.17
[Javascript] this  (0) 2022.03.09