320x100
320x100
제너레이터
: 일반 함수는 하나의 값만을 반환
: 제너레이터를 사용하면 여러 개의 값을 필요에 따라 하나씩 반환 (yield) 가능
: 제너레이터와 이터러블 객체를 함께 사용하면 손쉽게 데이터 스트림을 만들 수 있음
제너레이터 함수
: function* 을 통해 생성
: 제너레이터 함수를 호출하면 코드가 실행되지 않고
대신 실행을 처리하는 특별 객체인 제너레이터 객체가 반환 됨
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}
※ function* f()와 function *f()는 같다
제너레이터와 이터러블
function* generateSequence() {
yield 1;
yield 2;
return 3;
}
let generator = generateSequence();
for(let value of generator) {
alert(value); // 1, 2가 출력됨
}
function* generateSequence() {
yield 1;
yield 2;
yield 3;
}
let sequence = [0, ...generateSequence()];
alert(sequence); // 0, 1, 2, 3
이터러블 대신 제너레이터 사용하기
let range = {
from: 1,
to: 5,
// for..of 최초 호출 시, Symbol.iterator가 호출됩니다.
[Symbol.iterator]() {
// Symbol.iterator는 이터레이터 객체를 반환합니다.
// for..of는 반환된 이터레이터 객체만을 대상으로 동작하는데, 이때 다음 값도 정해집니다.
return {
current: this.from,
last: this.to,
// for..of 반복문에 의해 각 이터레이션마다 next()가 호출됩니다.
next() {
// next()는 객체 형태의 값, {done:.., value :...}을 반환해야 합니다.
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
}
};
// 객체 range를 대상으로 하는 이터레이션은 range.from과 range.to 사이의 숫자를 출력합니다.
alert([...range]); // 1,2,3,4,5
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
: 위 두 코드는 동일한 결과를 출력한다
제너레이터 컴포지션
: 제너레이터 안에 제너레이터를 임베딩 할 수 있게 해주는 제너레이터의 특별 기능
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를 사용해 제너레이터 안밖으로 정보 교환하기
function* gen() {
// 질문을 제너레이터 밖 코드에 던지고 답을 기다립니다.
let result = yield "2 + 2 = ?"; // (*)
alert(result);
}
let generator = gen();
let question = generator.next().value; // <-- yield는 value를 반환합니다.
generator.next(4); // --> 결과를 제너레이터 안으로 전달합니다.
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
: next를 통해 value가 next의 값과 같은 yield의 다음 yield를 반환
generator.throw
: 에러 핸들링
function* generate() {
let result = yield "2 + 2 = ?"; // Error in this line
}
let generator = generate();
let question = generator.next().value;
try {
generator.throw(new Error("데이터베이스에서 답을 찾지 못했습니다."));
} catch(e) {
alert(e); // 에러 출력
}
Refference
300x250
728x90
'Programming > JavaScript' 카테고리의 다른 글
모던 자바스크립트 (모듈) 12-1. 모듈 (0) | 2022.04.23 |
---|---|
모던 자바스크립트 11. async 이터레이터와 제너레이터 (0) | 2022.04.23 |
모던 자바스크립트 (promise와 async, await) 9-3. async와 await (0) | 2022.04.23 |
모던 자바스크립트 (promise와 async, await) 9-2. 프라미스 체이닝 / 에러 핸들링 / API / 프라미스화 / 마이크로 태스크 (0) | 2022.04.23 |
모던 자바스크립트 (promise와 async, await) 9-1. 콜백 / 프라미스 (0) | 2022.04.23 |