일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- k8s
- kubernetes
- 컴퓨터공학
- 솔리디티
- 이슈
- 리액트
- TypeScript
- 파이썬
- 웹
- 알고리즘
- es6
- JavaScript
- AWS
- CSS
- 백준
- 프론트엔드
- 타입스크립트
- BFS
- HTML
- 이더리움
- 자바스크립트
- node.js
- next.js
- 클라우드
- docker
- 백엔드
- 가상화
- react
- 블록체인
- 쿠버네티스
- Today
- Total
즐겁게, 코드
제너레이터부터 리덕스 사가까지 - 01. 제너레이터 본문
제너레이터를 활용하면 함수의 실행을 중간에 멈췄다가 재개할 수 있습니다.
// 화살표 함수 형태로는 제너레이터를 생성할 수 없습니다.
function* f1() {
yield 10;
yield 20;
return "완료";
}
const gen = f1();
보시면 function 키워드 뒤에 * 이 붙어있는 것을 확인할 수 있는데요, function*
키워드는 제너레이터를 정의하는 문법입니다.
(따라서 화살표 함수 형태로는 제너레이터 함수를 생성할 수 없습니다.)
함수 내에 존재하는 yield
는 함수의 실행을 잠깐 멈출 수 있는 분기이며, 제너레이터 함수를 실행하면 제너레이터 객체를 반환합니다.
yield 키워드
yield
키워드에 대해 조금 자세히 다루자면 yield
는 제너레이터 내부의 값을 외부로 반환할 수도 있고, 외부의 값을 제너레이터 내부로 가져올 수도 있는 창구의 역할을 합니다.
이 때 처음 호출되는 generator.next()
는 인자를 가질 수 없다는 점에 유의하셔야 합니다. (가진다 해도 무시됩니다!)
function* gen() {
let answer1 = yield "2 + 2 = ?";
console.log(answer1);
let answer2 = yield "3 + 6 = ?";
console.log(answer2);
}
let generator = gen();
// 제너레이터가 "2 + 2 = ?" 가 리턴됩니다. (첫 번째 next에서는 인자를 추가할 수 없습니다.)
const q1 = generator.next().value;
console.log(q1); // "2 + 2 = ?"
// 4를 제너레이터 내의 answer1에 전달하고, 제너레이터는 "3 + 6 = ?" 을 리턴합니다.
const q2 = generator.next(4).value;
console.log(q2); // "3 + 6 = ?"
generator.next(9); // 제너레이터 내의 answer2에 9를 전달합니다.
제너레이터의 메서드
제너레이터 객체에는 next
, return
, throw
라는 메서드가 있습니다.
이 중 next
메서드를 호출하면 yield
키워드를 만날 때까지 실행되고 데이터 객체를 *반환합니다.
(* 눈썰미가 좋다면 아마 눈치채셨겠지만, yield의 존재를 제외하면 이는 이터레이터 프로토콜과 완전히 동일합니다.)
[데이터 객체의 형태]
{ value: 10, done: false }
{ value: 20, done: true }
// done 속성이 한번 참으로 바뀌면 거짓으로 되돌릴 수 없으며
// 이후의 value는 반드시 undefined로 고정됩니다.
{ value: undefined, done: true }
이 데이터 객체는 value 와 done 속성으로 이루어져 있는데요, value 속성에는 yield
와 return
값으로 지정된 값이, done 속성은 yield
키워드가 더이상 앞에 없을 때까지 false 값이 담기게 됩니다.
[제너레이터 객체의 next 메서드 사용 예시]
function* f1() {
yield 10;
yield 20;
return "완료";
}
const gen = f1();
console.log(gen.next()); // { value: 10, done: false }
console.log(gen.next()); // { value: 20, done: false }
console.log(gen.next()); // { value: '완료', done: true }
console.log(gen.next()); // { value: undefined, done: true }
다음은 제너레이터 객체의 return
메서드입니다.
하나 주의해야 할 것이, return
메서드는 제너레이터가 리턴하는 값이 아닌 인자로 받은 값 을 리턴하고 done 속성값을 참으로 바꿉니다.
function* f1() {
yield 10;
yield 20;
return "이 값이 리턴될 것 같지만";
}
const gen = f1();
console.log(gen.next()); // { value: 10, done: false }
console.log(gen.return("이 값이 리턴됩니다.")); // {value: "이 값이 리턴됩니다.", done: true }
console.log(gen.next()); // { value: undefined, done: true}
return
메서드를 호출하면 done 속성이 곧바로 참으로 바뀌므로, 이후에 실행하는 next
메서드는 값을 리턴하지 못하게 됩니다.
마지막 메서드는 throw
메서드입니다.
function* f1() {
try {
yield 10;
yield 20;
return "완료";
} catch (error) {
console.log("에러 코드 :", error);
}
}
const gen = f1();
console.log(gen.next()); // { value: 10, done: false }
console.log(gen.throw("404")); // 에러 코드 : 404
// { value: undefined, done: true }
throw
메서드의 인자로 주어진 값이 캐치문의 인자로 전달되며, 캐치문을 실행한 후 done 속성은 참이 됩니다.
이게 제너레이터가 가진 정말 모든 특징입니다만... 이걸 대체 어디에 써먹을 수 있는 걸까요?
next
메서드를 소개할 때 잠깐 스치듯이 이터레이터 프로토콜과의 유사성을 언급했는데요, 다음 시간에는 반복자로써의 제너레이터 사용 방법을 소개하도록 하겠습니다.
'💬 언어 > Javascript' 카테고리의 다른 글
nullish coalescing 연산자로 널 참조 방지하기 (0) | 2021.05.02 |
---|---|
변수의 호이스팅, 그리고 TDZ의 함정 (0) | 2021.04.11 |
동적으로 모듈 불러오기 (0) | 2021.03.09 |
requestAnimationFrame 으로 애니메이션 구현하기 (0) | 2021.02.23 |
find, some 메서드로 배열 검사하기 (0) | 2021.02.21 |