[JavaScript] Generator

Narcoker·2022년 8월 29일
0

JavaScript

목록 보기
19/55

Generator

함수의 실행을 중간에 멈췄다가 재개할 수 있는 기능이다.
function 옆에 * 을 적어서 사용하고 내부에 yield 키워드를 사용한다.
yield에서 함수의 실행을 멈출 수 있다.
Redux Saga에서 많이 사용된다.

new를 사용할 수 없다. 단일 함수용
constructor가 없다.

function* fn(){
  yield 1;
  yield 2;
  yield 3;
  return "finish";
}
const a = fn();

next()

Generator 함수를 실행하면 Generator 객체를 반환한다.
따라서 실행하면 함수가 실행되지 않는다.
yield 키워드는 중단점을 의미하는데 next() 메소드를 사용하면
근처의 yield 까지 실행되고 데이터 객체를 반환한다.
이 객체는 value와 done Property 를 가진다.
이때 value는 yield 오른쪽에 있는 값이다. 값을 생략하면 undefined 이다.

function* fn(){
  console.log(1);
  yield 1;
  console.log(2);
  yield 2;
  console.log(3);
  console.log(4);
  yield 3;
  return "finish";
}
const a = fn();
a.next(); // 1 {value: 1, done: false}
a.next(); // 2 {value: 2, done: false}
a.next(); // 3 4 {value: 3, done: false}
a.next(); // {value: finish, done: true}
a.next(); // {value: undefined, done: true}

return()

호출 시 done Property 값이 true가 된다.
파라미터에 넣은 값이 value가 되고 없으면 undefined가 된다.

이후 next를 실행시 value를 얻을 수 없고 done는 true이다.

a.return('end'); // {value: 'end', done: true}
a.next(); // {value: undefined, done: true}

throw()

매개변수로 error 객체를 넣어 실행하면 try catch 문에서 catch문으로 간다.

function* fn(){
  try{
  	console.log(1);
  	yield 1;
 	
    console.log(2);
  	yield 2;
	
    console.log(3);
  	console.log(4);
  	yield 3;

    return "finish";
  } catch(e){
    yield 20;
  }
 
  yield 30;
}
const a = fn();
a.next(); // 1 {value: 1, done: false}
a.next(); // 2 {value: 2, done: false}
a.throw(new Error('err')); // {value: 20, done: false}
a.next(); // {value: 30, done: false}
a.next(); // {value: undefined, done: true}

만약 Generator 함수 내부에서 에러가 발생하면
즉시 종료된다. {value: undefined, done: true}

iterable

iterable이란 반복이 가능하다는 뜻이다.

  • Symbol.iterator 메서드가 있다.
  • Symbol.iterator 는 iterator를 반환해야한다.
    for of 로 출력이 가능하다.

Generator도 iterable이다.

function* fn(){
  yield 4;
  yield 5;
  yield 6;
}
const a = fn();
for(let s of a){
  console.log(s);
}
// 4
// 5
// 6

iterator

  • next 메서드를 가진다.
  • next 메서드는 value와 done 속성을 가진 객체를 반환한다.
  • 작업이 끝나면 done은 true가 된다.

next() 인수 전달

Generator는 외부로 부터 값을 입력할 수 있다.

function* fn(){
  const num1 = yield "첫번째 숫자를 입력해주세요";
  console.log(num1);
  const num2 = yield "두번째 숫자를 입력해주세요";
  console.log(num2);
  return num1 + num2;
}
const a = fn();
a.next(); 
// "{value: 첫번째 숫자를 입력해주세요, done: false"}
a.next(2); 
// 2
// "{value: 두번째 숫자를 입력해주세요, done: false
a.next(4);
// 4
// {value: 6, done, true}

값을 미리 만들어두지 않음

필요한 순간에만 값을 만들어내기 때문에 다음과같은 무한 반복문에서도
브라우저가 뻗지 않는다.
next()로 호출할때마다 값을 주기 때문이다.

function* fn() {
  let index = 0;
  while(true) {
    yield index++:
  }
}
const a = fn();
a.next();
// {value: 0, done: false}
a.next();
// {value: 1, done: false}
a.next();
// {value: 2, done: false}
// ...

yield*

다른 Generator 함수 호출을 할 수 있다.
yield* 옆에는 반복가능한 모든 객체가 올 수 있다.
done이 true가 될때까지 값을 펼쳐준다.

function* gen1(){
  yield "w";
  yield "o";
  yield "r";
  yield "l";
  yield "d";
}

function* gen2(){
  yield "Hello,";
  yield* gen1();
  yield "!";
}
console.log(...gen2());
// Hello, w o r l d !
function* sports(){
	yield* [10,20];
};

const obj = sports();
console.log(obj.next()); // {value: 10, done: false}
console.log(obj.next()); // {value: 20, done: false}

만약 할당문에 yield가 들어간다면 value 값이 변수값에 할당되지 않는다.
할당되기전에 반환하기 때문이다.

그 다음 next() 메서드에서 파라미터로 지정된 값이 해당 변수의 값으로 할당된다.

function* sport(one){
  let two = yield one;
  let param = yield one + two; // yield undefined + two
  yield param + one; 
};

const obj = sports(10);

console.log(obj.next()); // {value: 10, done: false}
console.log(obj.next()); // {value: NaN, done: false}
console.log(obj.next(20)); // {value: 30, done: false}
console.log(obj.next()); // {value: undefined, done: True}

for-of 문 사용

for-of 사용 시 value 값만 변수에 들어간다.

function* sports(count){
	while(true){
    	yield ++count;
   };
};

for (let point of sports(10)){
	log(point);
    if (point > 12) {
		break;
	};
}

/* 
11
12
13
*/
profile
열정, 끈기, 집념의 Frontend Developer

0개의 댓글