상세 컨텐츠

본문 제목

JavaScript - Generator

Programming Language/JavaScript

by Yongari 2023. 1. 25. 22:02

본문

 

 

Generator 

 

Generator 객체는 generator function으로부터 반환되며 반복가능한 프로토콜과 반복자 프로토콜을 준수함

인스턴스 메서드는 다음과 같이 3가지가 있음

 

1. Generator.prototype.next()

2. Generator.prototype.return()

3. Generator.prototype.throw()

 

 

Constructor

 

이 객체는 바로 인스턴스화 될 수 있음, 제너레이터 함수를 통해 Generator 인스턴스를 반환할 수 있음

function* generator() {
  yield 1;
  yield 2;
  yield 3;
  yield 4; 
  yield 5;
  yield "4";
  yield "test";
}

const gen = generator(); // "Generator { }"

console.log(gen.next().value); // 1

console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
console.log(gen.next().value);
console.log(gen.next().value);

console.log(gen.next().value);
console.log(gen.next().value);
console.log(gen.throw());
console.log(gen.return())
console.log(gen.next().value);

 

무한 제너레이터 

제너레이터 함수를 사용하고 무한루프를 정의하면 잠재적으로 무한한 데이터구조를 정의할 수 있음

 

function* infinite() {
  let index = 0;

  while (true) {
    yield index++;
  }
}

const generator2 = infinite(); // "Generator { }"

console.log(generator2.next().value); 
console.log(generator2.next().value); 
console.log(generator2.next().value);
console.log(generator2.next().value); 
console.log(generator2.next().value); 
console.log(generator2.next().value); 
console.log(generator2.next().value); 
console.log(generator2.next().value); 
console.log(generator2.next().value); 

결과 

0
VM1057:12 1
VM1057:13 2
VM1057:14 3
VM1057:15 4
VM1057:16 5
VM1057:17 6
VM1057:18 7
VM1057:19 8

 

 

 

 

제너레이터 함수를 만들때에는 function* 이라는 키워드를 사용합니다. 그리고 제너레이터 함수를 호출했을 때는 한 객체가 반환되는데요 이를 제너레이터라고 부릅니다.

 

함수를 작성한 뒤에는 다음 코드를 사용해 제너레이터를 생성하고 테스트해보세요.

 

코드

function* generatorFunction() {
    console.log('안녕하세요?');
    yield 1;
    console.log('제너레이터 함수');
    yield 2;
    console.log('function*');
    yield 3;
    return 4;
}

 

 

결과

const generator = generatorFunction();
undefined
generator.next();
VM125:2 안녕하세요?
{value: 1, done: false}
generator.next();
VM125:4 제너레이터 함수
{value: 2, done: false}
generator.next();
VM125:6 function*
{value: 3, done: false}
generator.next();
{value: 4, done: true}
generator.next();
{value: undefined, done: true}
generator.next();
{value: undefined, done: true}
generator.next();
{value: undefined, done: true}
generator.next();
{value: undefined, done: true}
generator.next();
{value: undefined, done: true}
generator.next();
{value: undefined, done: true}
generator.next();
{value: undefined, done: true}

 

next 함수를 호출 할 때 인자를 전달해서 제너레이터 함수 내부에서 사용할 수도 있습니다.

코드

function* sumGenerator() {
    console.log('sumGenerator이 시작됐습니다.');
    let a = yield;
    console.log('a값을 받았습니다.');
    let b = yield;
    console.log('b값을 받았습니다.');
    yield a + b;
}



결과

undefined
const sum = sumGenerator();
undefined
sum.next()
VM405:2 sumGenerator이 시작됐습니다.
{value: undefined, done: false}
sum.next()
VM405:4 a값을 받았습니다.
{value: undefined, done: false}
sum.next()
VM405:6 b값을 받았습니다.
{value: NaN, done: false}
sum.next()
{value: undefined, done: true}
sum.next()
{value: undefined, done: true}
sum.next(1)
{value: undefined, done: true}
sum.next(2)
{value: undefined, done: true}
const sum2 = sumGenerator();
undefined
sum2.next(1)
VM405:2 sumGenerator이 시작됐습니다.
{value: undefined, done: false}
sum2.next(3)
VM405:4 a값을 받았습니다.
{valu

 

 

 

Generator로 모니터링하기

Generator를 통해 모니터링을 할 수 있습니다. 다음 코드를 크롬 개발자도구에서 실행하면 하단의 결과와 같습니다. 

 

 

모니터링 코드

function* watchGenerator() {
    console.log('모니터링 시작!');
    while(true) {
        const action = yield;
        if (action.type === 'HELLO') {
            console.log('안녕하세요?');
        }
        if (action.type === 'BYE') {
            console.log('안녕히가세요.');
        }
    }
}

 

 

 

결과

const watch2 = watchGenerator();
undefined
watch2.next();
VM1461:2 모니터링 시작!
{value: undefined, done: false}
watch2.next({ type: "HELLO" });
VM1461:6 안녕하세요?
{value: undefined, done: false}
watch2.next({ type: "BYE" });
VM1461:9 안녕히가세요.
{value: undefined, done: false}
watch2.next({ type: "BYE" });
VM1461:9 안녕히가세요.
{value: undefined, done: false}
watch2.next({ type: "BYE" });
VM1461:9 안녕히가세요.
{value: undefined, done: false}
watch2.next({ type: "HELLO" });
VM1461:6 안녕하세요?
{value: undefined, done: false}
watch2.next({ type: "HELLO" });
VM1461:6 안녕하세요?
{value: undefined, done: false}
watch2.next();
VM1461:5 Uncaught TypeError: Cannot read properties of undefined (reading 'type')
    at watchGenerator (<anonymous>:5:20)
    at watchGenerator.next (<anonymous>)
    at <anonymous>:1:8
watchGenerator @ VM1461:5
(익명) @ VM1731:1
watch2.next();
{value: undefined, done: true}
watch2.next();
{value: undefined, done: true}
watch2.next();
{value: undefined, done: true}
watch2.next({ type: "HELLO" });
{value: undefined, done: true}
watch2.next({ type: "BYE" });
{value: undefined, done: true}

 

 

참고:  

MDN 링크

밸로퍼트 리액트

관련글 더보기