JavaScript - 제너레이터

치맨·2024년 1월 12일
0

javascript

목록 보기
23/23
post-thumbnail

목차

제너레이터란

  • 제너레이터는 코드 블록의 실행을 일시 중지했다가 필요한 시점에 재개할 수 있는 특수한 함수입니다.

  • 제너레이터 함수는 function* 키워드로 선언합니다. *(애스터리스크)의 위치는 function 키워드와 함수 이름 사이라면 어디든지 상관없지만 일관성을 위해 function 키워드 바로 뒤에 붙이는걸 권장합니다.

  • 하나 이상의 yield 표현식을 포함합니다.

  • 제너레이터 함수는 화살표 함수로 정의할 수 없습니다.

  • 제너레이터 함수는 new 연산자와 함께 생성자 함수로 호출할 수 없습니다.

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

제너레이터와 일반 함수 차이

  1. 제너레이터 함수는 함수 호출자에게 함수 실행의 제어권을 양도할 수 있다.
// 일반 함수
function normalFunction() {
  console.log('Start of normal function');
  console.log('End of normal function');
}

// 제너레이터 함수
function* generatorFunction() {
  console.log('Start of generator function');
  yield; // 중간에 일시정지
  console.log('End of generator function');
}

// 일반 함수 실행
normalFunction(); // 호출하면 Start~End까지 호출될 때 사용자가 제어할 수 없다.

// 제너레이터 함수 실행
const generator = generatorFunction();
generator.next(); // Start of generator function 출력 후 일시정지
// 만약 End of 까지 출력하고 싶다면? => next를 호출
generator.next(); // End of generator function 출력 후 일시정지
  1. 제너레이터 함수는 함수 호출자와 함수의 상태를 주고받을 수 있다.
  • 일반함수의 경우 매개변수를 통해 외부에서 값을 주입받고, 결과값을 반환하는 형태로 단방향으로 데이터가 전달된다. => 일반 함수가 실행되는 상황에는 함수 외부에서 내부로 값을 전달하여 함수의 상태를 변경할 수 없다.
  • 제너레이터 함수의 경우 양방향으로 함수의 상태를 주고받을 수 있다.
  function* gen() {
    let ask1 = yield '2 + 2 = ?';

    console.log(ask1);

    let ask2 = yield '3 * 3 = ?';

    console.log(ask2);
  }
  
  // 제너레이터 함수 실행
  let generator = gen();
  // '2 + 2 = ?' 질문 
  console.log(generator.next().value);
  // value 값으로 4를 전달
  console.log(generator.next(4).value);
  // 4가 출력, '3 * 3 = ?' 질문
  console.log(generator.next(9).done);
  // 9를 전달,  
  // 9출력, true 출력 
  
  // console에 찍히는 모습
  // 2 + 2 = ?
  // 4
  // 3 * 3 = ?
  // 9
  // true
          

제너레이터 객체

  • 제너레이터 객체는 제너레이터 함수를 호출하면 반환하는 객체입니다.
  • 제너레이터 함수가 반환한 제너레이터 객체는 이터러블이면서 동시에 이터레이터 입니다.

    이터러블? 이터레이터? 이터러블, 이터레이터 확인하러 가기

  • 쉽게 말하면 제너레이터는 Symbol.iterator 메서드를 가지고 있는 이터러블 이면서, next메서드를 가지고 있고, 이를 통해 이터레이터 리절트 객체(value,done 프로퍼티를 가진 객체)를 반환하는 이터레이터입니다.
  • 제너레이터는 next()를 가지고 있는 이터레이터지만 이터레이터에 없는 return, throw메서드를 가지고 있습니다.

제너레이터의 일시 중지와 재개

  • 제너레이터는 어떻게 일시 중지하고, 재개할까?
  • yield 키워드를 통해 모든걸 통제합니다.
  • 즉 yield 키워드를 통해 제너레이터 함수의 실행을 일시 중지시키거나, yield 뒤에 오는 표현식의 평가 결과를 제너레이터 함수 호출자에게 반환합니다.

제너레이터의 활용

이터러블의 구현

  • 이터러블을 직접 구현한것과 제너레이터의 차이를 확인해보겠습니다.

  • 우선 이터레이션 프로토콜을 준수하여 무한 피보나치 수열을 생성하는 함수를 구현

  • 제너레이터를 활용한 무한 피보나치 함수

  • 확실히 간단해진 걸 확인할 수 있습니다.

제너레이터를 통한 비동기 처리

  • 제너레이터 함수는 next메서드와 yield 표현식을 통해 호출자와 함수의 상태를 주고받을 수 있습니다.
  • 이러한 특성을 활용하여 프로미스를 사용한 비동기 처리를 동기 처리처럼 구현할 수 있습니다.
  • 즉 프로미스의 후속 처리 메서드(try, catch, finally)없이 비동기 처리 결과를 반환할 수 있습니다.

  • 제너레이터를 통해 비동기함수를 동기처럼 구현할 수 있는 장점이 있지만 위 사진에 나오는것 과 같이 코드가 장황하고 가독성도 나빠졌습니다.

훌륭한 개발자들은 이런거 또 못보기 때문에 제너레이터보다 더 간단하고 가독성 좋게 비동기 처리를 동기처리 처럼 동작하도록 구현할 수 있는 기술을 개발해냈습니다.

그것은 바로 async, await입니다. 이건 다음 글에서 또 작성해보겠습니다.

참고

profile
기본기가 탄탄한 개발자가 되자!

0개의 댓글