본문 바로가기
프로그래밍 개발/JS ES6+

Javascript ES6+ Generator

by Jinseok Kim 2020. 12. 18.
반응형

 

 

 

 

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

댓글