[JS] Generator

Hadam Cho·2022년 7월 10일
1

Frontend

목록 보기
3/8
post-thumbnail

1개 혹은 0개의 값을 반환하는 일반 함수와는 다르게 여러 개의 값을 필요에 따라 반환yield 할 수 있습니다.

Generator Function

function*을 통해 Generator 객체를 생성할 수 있습니다.

function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

const generator = generateSequence();
console.log(generator.toString()); // [object Generator]

Methods

Generator.prototype.next()

가장 가까운 yield 문을 만날 때까지 실행되며, valuedone property를 가진 객체를 반환합니다.

  • done (boolean): iterator가 다음 value를 생성할 수 있으면 false, 함수 코드 실행이 끝났으면 true
  • value (any): iterator로부터 반환되는 값

done이 true일 경우, value는 return 값이다.

Syntax

generatorObject.next(value)

Examples

❶ Using next()

function* gen() {
  yield 1;
}

const g = gen(); // "Generator { }"
g.next();        // "Object { value: 1, done: false }"
g.next();        // "Object { value: undefined, done: true }"

❷ Sending values to the generator

function* gen() {
  while (true) {
    const value = yield null;
    console.log(value);
  }
}

const g = gen();
g.next(1);
// "{ value: null, done: false }"
g.next(2);
// 2
// "{ value: null, done: false }"

종료 후 next() 호출 시에는 계속 { value: undefined, done: true }만 return 됩니다.

Generator.prototype.return()

현재 일시 중단된 위치에 return문이 삽입된 것처럼 동작하여, parameter로 제공된 value를 반환하고 Generator를 종료시킵니다.

Syntax

generatorObject.return(value)

Examples

❶ Using return()

function* gen() {
  yield 1;
  yield 2;
  yield 3;
}

const g = gen();

g.next();        // { value: 1, done: false }
g.return('foo'); // { value: "foo", done: true }
g.next();        // { value: undefined, done: true }

❷ Using return() with try...finally

function* gen() {
  yield 1;
  try {
    yield 2;
    yield 3;
  } finally {
    yield 'cleanup';
  }
}

const g1 = gen();
g1.next(); // { value: 1, done: false }

// try...catch 실행 전 return()
g1.return('early return'); // { value: 'early return', done: true }


const g2 = gen();
g2.next(); // { value: 1, done: false }
g2.next(); // { value: 2, done: false }

// try...catch 실행 후 return()
g2.return('early return'); // { value: 'cleanup', done: false }

// 값 보존
g2.next(); // { value: 'early return', done: true }

Generator.prototype.throw()

현재 일시 중단된 위치에 throw문이 삽입된 것처럼 동작하여, 에러 핸들링이 가능하게 한다.

Syntax

generatorObject.throw(exception)

exception은 디버깅을 위해 instanceof Error인 것이 유용하다.

Example

function* gen() {
  while (true) {
    try {
      yield 42;
    } catch (e) {
      console.log('Error caught!');
    }
  }
}

const g = gen();
g.next();
// { value: 42, done: false }
g.throw(new Error('Something went wrong'));
// "Error caught!"
// { value: 42, done: false }

Iterable

Generator는 Symbol.iterator method가 존재하기 때문에 Iterable 객체입니다.
따라서 for of문 사용이 가능합니다.

function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

const generator = generateSequence();

for(let value of generator) {
  console.log(value);
}

실행 결과

1
2

주의 사항

위 예시를 보면 알겠지만, 3은 출력되지 않습니다.
{ done: true }일 때 마지막 value를 무시하기 때문입니다.
모든 값이 출력되기를 원한다면 yield로 값을 반환해야 합니다.

Spread Operator

function* generateSequence() {
  yield 1;
  yield 2;
  yield 3;
}

const sequence = [...generateSequence()];
console.log(sequence); // [1, 2, 3]

Iterable 객체이므로 Spread Operator도 사용 가능합니다.

Iterator

next() method를 가지고 있기 때문에 iterator입니다.

Iterable, Iterator의 자세한 내용은 여기서 확인할 수 있습니다.



Related Content
[JS] Iteration protocols


참고 문서
Generator (MDN)
JAVASCRIPT.INFO 제너레이터

profile
(。・∀・)ノ゙

0개의 댓글