[JavaScript] 제너레이터

수민🐣·2022년 12월 13일
0

JavaScript

목록 보기
30/32

제너레이터(generator)

코드 블록의 실행을 일시 중지 (블로킹) 했다가 필요한 시점에 재개할 수 있는 특수한 함수다.
일반 함수는 하나의 값만을 반환하지만 제너레이터를 사용하면여러 개의 값을 필요에 따라 하나씩 반환(yield)할 수 있다.

제너레이터 함수

function* 키워드를 이용

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

제너레이터 함수를 호출하면 코드가 실행되지 않고, 대신 실행을 처리하는 특별 객체 제너레이터 객체가 반환된다.

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

// '제너레이터 함수'는 '제너레이터 객체'를 생성한다.
// 아직 함수 본문 코드는 실행되지 않았다.
let generator = generateSequence();
alert(generator); // [object Generator] 

next() 메서드는 제너레이터의 주요 메서드이다.
가장 가까운 yield <value>문을 만날 때까지 실행이 지속되며 value를 생략할 수 있는데 이 경우에는 undefined가 된다.
yield <value>문을 만나면 실행이 멈추고 산출하고자 하는 값인 value 가 바깥 코드에 반환된다.

next()는 항상 두 프로퍼티를 가진 객체를 반환한다.

  • value : 산출 값
  • done : 함수 코드 실행이 끝났으면 true, 아니라면 false
function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

let generator = generateSequence();

let one = generator.next();

alert(JSON.stringify(one)); // {value: 1, done: false}
// 현재로서는 첫 번째 값만 받았으므로 함수 실행은 두 번째 줄에서 멈췄다.
// 다시 호출
let two = generator.next();

alert(JSON.stringify(two)); // {value: 2, done: false}

// 다시 호출하면 실행은 return문에 다다르고 함수가 종료
let three = generator.next();

alert(JSON.stringify(three)); // {value: 3, done: true} 종료

제너레이터와 이터러블

for..of반복문을 사용해 값을 얻을 수 있고 전개문법(...)으로도 가능

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

let generator = generateSequence();

for(let value of generator) {
  alert(value); // 1, 2가 출력됨
}

3은 출력되지 않는다. for..of이터레이션이 done:true일 때 마지막value를 무시하기 때문에 yield : 3으로 바꿔야 값이 반환됨

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

let sequence = [0, ...generateSequence()];

alert(sequence); // 0, 1, 2, 3

yield를 사용해 제너레이터 안,밖으로 정보 교화

yield가 양방향 길 같은 역할을 한다. 즉, 결과를 바깥으로 전달할 뿐만 아니라 값을 제너레이터 안으로 전달한다.
값을 안,밖으로 전달하라면 generator.next(arg)를 호출해야 한다. 이 때argyield의 결과가 된다.

function* gen() {
  // 질문을 제너레이터 밖 코드에 던지고 답을 기다립니다.
  let result = yield "2 + 2 = ?"; // (*)

  alert(result);
}

let generator = gen();

let question = generator.next().value; // <-- yield는 value를 반환합니다.

generator.next(4); // --> 결과를 제너레이터 안으로 전달합니다

1.generator.next()를 처음 호출할 땐 항상 인수가 없어야 한다. 그래서 generator.next()를 호출하면 실행이 시작되고 첫번 째yield "2 + 2 = ?"의 결과가 반환된다.
2.yield의 결과가 제너레이터를 호출하는 외부 코드에 있는 변수 question에 할당
3.generator.next(4)에서 제너레이터가 다시 시작되고 4는 result에 할당

function* gen() {
  let ask1 = yield "2 + 2 = ?";

  alert(ask1); // 4

  let ask2 = yield "3 * 3 = ?"

  alert(ask2); // 9
}

let generator = gen();

alert( generator.next().value ); // "2 + 2 = ?"

alert( generator.next(4).value ); // "3 * 3 = ?"

alert( generator.next(9).done ); // true

generator.throw

결과가 될 것을 제너레이터 안에 전달하기도 하고 외부 코드가 에러를 만들거나 던질 수도 있다.
에러를 yield안으로 전달하려면 generator.throw(err)를 호출해야한다. 호출하면 erryield가 있는 줄로 던져진다.

function* gen() {
  try {
    let result = yield "2 + 2 = ?"; // (1)

    alert("위에서 에러가 던져졌기 때문에 실행 흐름은 여기까지 다다르지 못합니다.");
  } catch(e) {
    alert(e); // 에러 출력
  }
}

let generator = gen();

let question = generator.next().value;

generator.throw(new Error("데이터베이스에서 답을 찾지 못했습니다.")); // (2)

0개의 댓글

관련 채용 정보