상세 컨텐츠

본문 제목

javascript.info - 제너레이터와 비동기 이터레이션

개발공부/개발공부

by Dal_pang 2023. 1. 2. 16:37

본문

제너레이터

: 일반 함수가 하나의 값을 반환하는 것과 다르게 여러 개의 값을 필요에 따라 하나씩 반환(yield)할 수 있다.
제너레이터와 이터러블 객체를 함께 사용해 데이터 스트림 만들기 가능.

제너레이터 함수 : function*

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


제너레이터와 이터러블
: 제너레이터는 이터러블이므로 for..of반복문을 사용해 값을 얻을 수 있다.

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

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

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


이터러블 대신 제너레이터 사용하기

let range = {
  from: 1,
  to: 5,

  *[Symbol.iterator]() { // [Symbol.iterator]: function*()를 짧게 줄임
    for(let value = this.from; value <= this.to; value++) {
      yield value;
    }
  }
};

alert( [...range] ); // 1, 2, 3, 4, 5

: range[Symbol.iterator]()는 제너레이터를 반환한다.

제너레이터 컴포지션
제너레이터 안에 제너레이터를 embedding, composing할 수 있게 해주는 제너레이터의 기능.
yield* 특수 문법을 사용하면 제너레이터를 다른 제너레이터에 끼워 넣기 가능.

function* generateSequence(start, end) {
  for (let i = start; i <= end; i++) yield i;
}

function* generatePasswordCodes() {

  // 0..9
  yield* generateSequence(48, 57);

  // A..Z
  yield* generateSequence(65, 90);

  // a..z
  yield* generateSequence(97, 122);

}

let str = '';

for(let code of generatePasswordCodes()) {
  str += String.fromCharCode(code);
}

alert(str); // 0..9A..Za..z

yield* 지시자는 실행을 다른 제너레이터에 위임함.
yield* gen이 제너레이터 gen을 대상으로 반복 수행, 산출 값들을 밖으로 전달.

'yield'를 사용해 제너레이터 안, 밖으로 정보 교환
yield는 양방향 길과 같은 역할을 한다.
generator.next(arg)를 사용. 인수 arg는 yield의 결과가 된다.

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

  alert(result);
}

let generator = gen();

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

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


*** 제너레이터의 외부 호출 코드는 next/yield를 이용해 결과 전달 및 교환!

generator.throw
외부 코드가 에러를 만들어 던지는 경우, generator.throw(err)를 호출해 에러를 yield 안으로 전달 가능.
제너레이터 안에서 예외 처리 하지 않은 경우, 제너레이터 외부 코드로 떨어져 나온다.
안, 밖에서 모두 에러를 잡지 못하면 호출 코드 바깥으로 떨어져 나가고 -> 거기서도 안 잡히면 스크립트 죽음.



제너레이터 요약
이터러블 객체를 쉽게 만들 수 있고,
웹 프로그래밍에서 데이터 스트림을 다루는 경우가 많은데, 이때 제너레이터를 유용하게 사용할 수 있다.


async 이터레이터와 제너레이터

Asynchronous iterator(비동기 이터레이터)를 사용하면 비동기적으로 들어오는 데이터를 필요에 따라 처리할 수 있다.
네트워크를 통해 데이터가 여러 번에 걸쳐 들어오는 상황 처리가능.
- 데이터가 비동기적으로 들어오는 경우 async 이터레이터와, async 제너레이터, for await..of사용.

일반 이터레이터와 async 이터레이터의 문법 차이.

  iterable async iterable
iterator를 반환하는 메서드 Symbol.iterator Symbol.asyncIterator
next()가 반환하는 값 {value:…, done: true/false} {value:…, done: true/false}를 감싸는 Promise

일반 제너레이터와 async 제너레이터의 문법차이.

  generators async generator
선언 function* async function*
next()가 반환하는 값 {value:…, done: true/false} {value:…, done: true/false}를 감싸는 Promise

용량이 큰 파일을 다운, 업로드할 때와 같이 띄엄띄엄 들어오는 데이터 스트림을 다룰 때, async 제너레이터 사용.

728x90

관련글 더보기