Generator와 Async/Await

joseph·2023년 5월 14일
0

개념정리

목록 보기
2/16

https://www.youtube.com/watch?v=ZrdHtL1gcEI&list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&index=37&pp=iAQB

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

일반 함수를 실행시키면 함수 구현부가 실행되고 반환 값이 반환된다.
하지만 generator함수를 실행시키면 함수 구현부가 실행되지 않고 generator객체가 반환된다

  • Generator는 중간에 실행을 중단하고 원하는 시점에 재개할 수 있도록 하는 함수다.
  • Generator 객체는 자체 실행 컨텍스트를 가지고 있다.
  • Generator와 Promise를 통해 동기적인 코드처럼 비동기 처리를 할 수 있다.
  • 위 방법이 표준화 된 것이 Async/Await

Generator 객체는?

  • iterator
    • next 매서드를 가진다
    • next매서드는 iteratorResult 객체를 반환한다 → iteratorResult
      • value와 done 프로퍼티를 갖는 객체
      • value : iterator가 반환하는 값
      • done: iterator가 끝남 여부를 알려주는 값 → iterable protocol(iterable)
        • 내부적으로 Symbol.iterator 매서드를 가진다
      • Symbol? → ES6에서 새로 생긴 원시 타입
        • Undefined
        • Null
        • Boolean
        • Number
        • String
        • Object
        • Symbol
      • Symbol은 왜 필요한가?
        다른 라이브러리와의 충돌을 막기 위해 객체에 Unique한 속성을 만들기 위해 필요하다.
      • 심볼은 Unique하기 때문에, description이 같아도 충돌하지 않는다.
      • 심볼은 객체의 속성을 순회하기 위한 for in
        Object.keys(obj)Object.getOwnPropertyNames(obj)에 걸리지 않는다.
        ```jsx
        var mySymbol1 = Symbol('mySymbol');
        var mySymbol2 = Symbol('mySymbol');
        mySymbol1 === mySymbol2;  **// false**
        
        var prop2 = Symbol('prop2')
        var obj = {
            prop1: 1,
            [prop2]: 2,
        };
        for (var key in obj) {
            console.log(key);  **// prop1 만 출력됨**
        }
        obj[prop2];  // 2, 대괄호[]로만 접근 가능
        ```
      • 대표적인 상용 Symbol은 Symbol.iterator, Symbol.hasInstance, Symbol.match가 있는데
        Symbol.iterator는 이터러블 한 객체를 정의하기 위한 심볼이다.
    • iterable protocol은 [for..of](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/for...of)구조에서 어떠한 value 들이 loop 되는 것과 같은 iteration 동작을 정의하거나 사용자 정의하는 것을 허용하고 spread연산과 구조분해 할당을 허용한다.

function* simpleGenerator(){
	console.log('generator start')
// 처음 next로 빨간색 까지 실행이 된다
	const result =  yield 1 + 2;
// 두번째 next로 파란색이 실행된다
	console.log('generator end, result is, result);
}

const gen = simpleGenerator()
const result = gen.next()
console.log(result)   // {value : 3, done : false} -> next는 iteratorResult를 반환하고
// iteratorResult는 value와 done 프로퍼티를 갖는다

const result2 = gen.next(10)  // next에 10을 담아서 실행시키면 generator end, result is 10

console.log(result2) // {value : undefined, done : true}

Generator 객체는 내부적으로 Generator State와 Generator Context slot을 가지고 있다.

Generator State는 Generator의 진행 상태와 관련된 값이 저장되고,

Generator Context는 Generator의 실행 컨텍스트가 저장된다

Generator State의 네 가지 단계

  1. Suspended Start

    → Generator 함수를 실행했을 때의 상태

  2. Executing

    → Generator객체의 next매서드를 실행한 시점의 상태

  3. Suspended Yield

    → Generator 객체의 yield키워드를 만난 시점의 상태

  4. Completed

    → return 키워드를 만나거나 함수의 끝에 도달했을 때의 상태

Generator의 실행 컨텍스트

  • 코드를 실행하면 Global 실행 컨텍스트가 생성된다 (그 안에는 greet와 greetGen이라는 식별자가 있는데 greet에는 generator 함수가 저장된고 greetGen은 아직 초기화가 안된 상태)
  • Generator함수가 호출되면 generator 실행 컨텍스트가 call stack에 push된다 → generator객체가 생성되고 이때의 generator객체의 상태값은 suspended start
  • generator컨텍스트가 pop되고 greetGen에 generator객체가 할당된다
  • next매서드가 호출되면 다시 generator 컨텍스트가 stack에 push되고 generator함수가 실행된다 → 이때 generator객체의 상태는 Executing
  • yield매서드를 만나게 되면 generator컨텍스트는 pop되고 그때 generator객체의 상태는 Suspended Yield
  • generator함수 내의 모든 코드가 실행되면 generator객체의 상태는 complete가 되고 종료

Generator와 Async/Await의 관계?

Async/Await은 Generator를 사용한 비동기 처리보다
더 편리하게 비동기처리를 하기 위해 등장했다.

→ Async/Await은 ES8에 도입되었다. Babel을 사용해서 async/await을 이전 브라우저로 돌려보면
generator함수를 실행시키는 유틸 함수가 필요하고 비동기처리를 하기 위해 yield함수를 쓰는 등 더 복잡하게 비동기 처리를 구현했다.

고로 async/await의 동작 과정은 위처럼 generator함수의 동작 과정을 뜯어보면 알 수 있다

profile
내일도 모레도 글피도 엉금엉금

0개의 댓글