반응형
Generator
- 중간에서 멈췄다가 이어서 실행할 수 있는 함수.
- function 키워드 뒤에 `*`를 붙여 표현하며, 함수 내부에는 `yield` 키워드를 활용한다.
- 함수 실행 결과에 대해 `next()` 메소드를 호출할 때마다 순차적으로 제너레이터 함수 내부의 `yield` 키워드를 만나기 전까지 실행하고, `yield` 키워드에서 일시정지한다.
- 다시 `next()` 메소드를 호출하면 그 다음 `yield` 키워드를 만날 때까지 함수 내부의 내용을 진행하는 식이다.
선언 방식
function* gene () { yield }
const gene = function* () { yield }
const obj = {
gene1: function* () { yield } //메소드 함수 가능
*gene2 () { yield } //함수 축약형으로도 가능
}
class A {
*gene () { yield }
}
iterable하게 적용할 수 있게 한다.
function* gene () {
console.log(1)
yield 1
console.log(2)
yield 2
console.log(3)
}
const gen = gene()
console.log(...gen)
// 1
// 2
// 3
//1 2 (yield 2에서 딱 멈춘다.)
const obj = {
a: 1,
b: 2,
c: 3,
*[Symbol.iterator] () { // 함수 축약형으로 제너레이터를 사용
for(let prop in this){
yield [prop, this[prop]] // for문 안의 yield 사용으로 객체 프로퍼티를 iterble 하게 함
}
}
}
console.log(...obj) // ["a", 1] ["b", 2] ["c", 3]
yield* [iterable] 방식
function* gene (){
yield* [1, 2, 3, 4, 5] //yield 자체에도 제너레이터 적용 가능
yield
yield* 'abcde'
//yield a;
//yield b;
//yield c;
//yield d; 와 같은 의미이다.
}
for(let prop of gene()){
console.log(prop)
}
//1
//2
//3
//4
//5
//undefined
//a
//b
//c
//d
//e
↓
중첩 적용도 가능하다.
function* gene1(){
yield [1, 10]
yield [2, 20]
}
function* gene2(){
yield [3, 20]
yield [4, 40]
}
function* gene3() {
yield* gene1()
yield* gene2()
yield*[[5,56],[4,40]]
}
const gen = gene3()
for(let [k, v] of gen){
console.log(k, v)
}
//1 10
//2 20
//3 20
//4 40
//5 56
//4 40
인자 전달하기
function* gene () {
let first = yield 1
let second = yield first + 2
yield second + 3
}
const gen = gene()
console.log(gen.next().value) // 1
console.log(gen.next().value) // 오류. 왜냐하면 이 호출 시점에서 first는 1이 아니기 때문이다.
console.log(gen.next().value) // 오류.
↓
next() 메소드 인자의 특성
function* gene () {
let first = yield 1
let second = yield first + 2
yield second + 3
}
const gen = gene()
console.log(gen.next().value) // 1
console.log(gen.next(10).value) // 12 왜냐하면 next 메소드 인자로 값을 넣어주면 변수 first에
// 넘겨주는 특성을 가지고 있기 때문이다.
Generator을 이용한 비동기 작업 실행
userId가 1000번 이후의 데이터를 가져와서 그중에 4번째에 위치한 User 정보를 가져오는 서버 코드이다.
const fetchWrapper = (gen, url) => fetch(url)
.then(res => res.json())
.then(res => gen.next(res));
function* getNthUserInfo() {
const [gen, from, nth] = yield;
const req1 = yield fetchWrapper(gen, `https://api.github.com/users?since=${from || 0}`);
const userId = req1[nth - 1 || 0].id;
console.log(userId); // 1004
const req2 = yield fetchWrapper(gen, `https://api.github.com/user/${userId}`);
console.log(req2); // id 1004의 user 정보들...
}
const runGenerator = (generator, ...rest) => {
const gen = generator();
gen.next();
gen.next([gen, ...rest]);
}
runGenerator(getNthUserInfo, 1000, 4);
반응형
'프로그래밍 개발 > JS ES6+' 카테고리의 다른 글
Javascript ES6+ Promise (0) | 2020.12.22 |
---|---|
Javascript ES6+ Class (0) | 2020.12.21 |
Javascript ES6+ Iterator (0) | 2020.12.18 |
Javascript ES6+ Iterable (0) | 2020.12.18 |
Javascript ES6+ Map (0) | 2020.12.16 |
댓글