함수의 실행을 중간에 멈췄다가 재개할 수 있는 기능이다.
function 옆에 * 을 적어서 사용하고 내부에 yield 키워드를 사용한다.
yield에서 함수의 실행을 멈출 수 있다.
Redux Saga에서 많이 사용된다.new를 사용할 수 없다.
단일 함수용
constructor가 없다.function* fn(){ yield 1; yield 2; yield 3; return "finish"; } const a = fn();
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}
호출 시 done Property 값이 true가 된다.
파라미터에 넣은 값이 value가 되고 없으면 undefined가 된다.이후 next를 실행시 value를 얻을 수 없고 done는 true이다.
a.return('end'); // {value: 'end', done: true} a.next(); // {value: undefined, done: true}
매개변수로 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이란 반복이 가능하다는 뜻이다.
- Symbol.iterator 메서드가 있다.
- Symbol.iterator 는 iterator를 반환해야한다.
for of 로 출력이 가능하다.
function* fn(){ yield 4; yield 5; yield 6; } const a = fn(); for(let s of a){ console.log(s); } // 4 // 5 // 6
- next 메서드를 가진다.
- next 메서드는 value와 done 속성을 가진 객체를 반환한다.
- 작업이 끝나면 done은 true가 된다.
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} // ...
다른 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 사용 시 value 값만 변수에 들어간다.
function* sports(count){ while(true){ yield ++count; }; }; for (let point of sports(10)){ log(point); if (point > 12) { break; }; } /* 11 12 13 */