JavaScript

제너레이터와 async/await

Hun-bot 2022. 7. 12. 20:38
728x90
반응형

제너레이터

코드 블록의 실행을 일시 중지했다가 필요한 시점에 재개할 수 있는 특수한 함수

  1. 제너레이터 함수는 함수 호출자에게 함수 실행의 제어권을 양도할 수 있다
    일반 함수를 호출하면 제어권이 함수에게 넘어가 제어가 불가능하지만 제너레이터는 가능
  2. 제너레이터 함수는 함수 호출자와 함수의 상태를 주고받을 수 있다
  3. 제너레이터 함수를 호출하면 제너레이터 객체를 반환한다
    제너레이터 함수를 호출하면 함수 코드를 실행하는 것이 아니라 이터러블이면서 동시에 이터레이터인 제너레이터 객체를 반환한다

제너레이터 함수의 정의

function* getDecFunc(){
  yield 1;
}

const genExpFunc=function* (){
  yield 1;
}

const obj={
  * genObjMethod(){
    yield 1;
  }
}

class MyClass{
  * getClsMethod(){
    yield 1;
  }
}

화살표 함수로 정의 불가능

*의 위치는 상관없지만 function키워드 바로 뒤에 붙이는 것을 권장한다

 

제너레이터 객체

제너레이터 함수를 호출하면 일반 함수처럼 함수 코드 블록을 실행하는 것이 아니라 제너레이터 객체를 생성해 반환한다

제너레이터 함수가 반환한 제너레이터 객체는 이터러블이면서 동시에 이터레이터다

function* genFunc(){
  yield 1;
  yield 2;
  yield 3;
}
const generator=genFunc()

console.log(Symbol.iterator in generator); //true

console.log(generator.next());//{ value: 1, done: false }
console.log(generator.return('End'));//{ value: 'End', done: true }

제너레이터 일시 중지와 재개

function* genFunc(){
  yield 1;
  yield 2;
  yield 3;
}
const generator=genFunc()

console.log(generator.next());
console.log(generator.next());
console.log(generator.next());
console.log(generator.next());

{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: undefined, done: true }

간단한 사용

function* genFunc(){

  const x=yield 1;
  const y=yield (x+10);
  return x+y
}
const generator=genFunc()

let res=generator.next()

console.log(res);

res=generator.next(10)
console.log(res);

res=generator.next(20)
console.log(res);

{ value: 1, done: false }
{ value: 20, done: false }
{ value: 30, done: true }

처음 호출하는  next 메서드에는 인수를 전달하지 않는다 ( 전달하면 무시된다 )

처음 value에는 1이 할당 -> 첫번째 yield값 1이 할당되는 것

다음 next메서드에 10이라는 인수를 전달하면 x 변수에 할당되고.. y 도 마찬가지로 다음 next(20)에 의해 20이 할당된다

 

제너레이터의 활용

const infiFibo=(function(){
  let [pre,cur]=[0,1]

  return{
    [Symbol.iterator](){return this;},

    next(){
      [pre,cur]=[cur,pre+cur]

      return {value:cur}
    }
  }
}())

for(const num of infiFibo){
  if(num>1000)break
  console.log(num);
}
-------------------------------------

const infiFiboGener=(function* (){
  let [pre,cur]=[0,1]

  while(true){
    [pre,cur]=[cur,pre+cur]
    yield cur;
  }
})

for(const num of infiFibo){
  if(num>1000)break
  console.log(num);
}

이터레이션으로 복잡하게 피보나치 수열을 만든 것을 제너레이터를 통해 간단하게 만들 수 있다

 

비동기 구현은 async/await

async는 언제나 프로미스를 반환함

await는 프로미스가 settled상태가 될 때까지 대기하다가 settled 상태가 되면 프로미스가 resolve한 처리 결과를 반환한다

const fetch=require('node-fetch')

const foo= async()=>{
  try{
    const wUrl='httpd:/dqwd'

    const res=await fetch(wUrl)
    const data= await res.json()
    console.log(data);
  }
  catch(err){
    console.error(err);
  }
}

foo()


프로미스를 반환하기에 이런것도 가능
try~catch문 쓰지 않고
foo()
.then()
.catch(console.error)

 

728x90
반응형