제너레이터란?제너레이터와 일반 함수의 차이제너레이터의 일시 중지와 재개이터레이터의 next 메서드와 달리 제너레이터 객체의 next 메서드에는 인수 전달이 가능함async/await ⇒ 콜백을 쓸 필요가 없게됨async 함수await 키워드에러 처리사용 예시
제너레이터란?
- ES6 에서 도입된 제너레이터는 코드 블록의 실행을 일시 중지했다가 필요한 시점에 재개할 수 있는 특수한 함수임
제너레이터와 일반 함수의 차이
제너레이터 함수는 함수 호출자(caller
)에게 함수 실행의 제어권을 양도할 수 있다.
- 일반 함수는 호출하면 제어권이 함수에게 넘어가고 함수 코드를 일괄 실행함. 즉,
caller
는 함수를 호출한 이후 함수 실행 제어할 수 없음
- 제너레이터 함수는 함수 실행을 함수 호출자가 제어할 수 있음. 즉, 함수 호출자가 함수 실행을 일시 중지시키거나 재개시킬 수 있다
- 이는 함수의 제어권을 함수가 독점하는 것이 아니라
caller
에게yield
할 수 있다는 것을 의미함
제너레이터 함수는 함수 호출자(caller
)와 함수의 상태를 주고 받을 수 있다.
- 일반 함수를 호출하면 매개변수를 통해 함수 외부에서 값을 주입받고 함수 코드를 일괄 실행하여 결과값을 함수 외부로 반환함. 즉, 함수가 실행되고 있는 동안에는 함수 외부에서 함수 내부로 값을 전달하여 함수의 상태를 변경할 수 없다
- 제너레이터 함수는 함수 호출자(
caller
)에게 상태를 전달할 수 있고 함수 호출자(caller
)로부터 상태를 전달받을 수도 있다.
제너레이터 함수를 호출하면 제너레이터 객체를 반환한다.
- 일반 함수 호출 시, 함수 코드 일괄 실행 후 값을 반환함
- 제너레이터 함수를 호출하면 함수 코드를 실행하는 것이 아니라 이터러블이면서 동시에 이터레이터인 제너레이터 객체를 반환함
제너레이터의 일시 중지와 재개
- 제너레이터는
yield
키워드와next
메서드를 통해 실행을 일시 중지했다가 필요한 시점에 다시 재개할 수 있음
- 제네레이터 함수를 호출하면 제너레이터 함수의 코드 블록이 실행되는 것이 아니라 제너레이터 객체를 반환
- 그 후,
next
메서드가 불리면 다음yield
표현식 까지만 실행함 - 제너레이터 객체의
next
메서드를 호출하면yield
표현식까지 실행되고 일시 중지됨. 이 때 함수의 제어권이 호출자로 양도(yield
)됨 next
메서드는value
,done
프로퍼티를 갖는iterator result
객체를 반환함
이터레이터의 next 메서드와 달리 제너레이터 객체의 next 메서드에는 인수 전달이 가능함
- 제너레이터 객체의 next 메서드에 전달한 인수는 제너레이터 함수의 yield 표현식을 할당받는 변수에 할당됨
- yield 표현식을 할당받는 변수에 yield 표현식의 평과 결과가 할당되지 않는다는점 주의!
- 함수 호출자는 next 메서드를 통해 yield 표현식까지 함수를 실행시켜 제너레이터 객체가 관리하는 상태(yield된 값)를 꺼내올 수 있고
- next 메서드에 인수를 전달해서 제너레이터 객체에 상태(yield 표현식을 할당받는 변수)를 밀어넣을 수 있음
async/await ⇒ 콜백을 쓸 필요가 없게됨
- ES8에서는 제너레이터보다 간단하고 가독성 좋게 비동기 처리를 동기 처리처럼 동작하도록 구현할 수 있는 async/await가 도입되었음
- async/await 는 프로미스를 기반으로 동작함. async/await를 사용하면 프로미스의 후속 처리 메서드에 콜백 함수를 전달해서 비동기 처리 결과를 후속 처리할 필요 없이 마치 동기 처리처럼 프로미스를 사용할 수 있다
async 함수
await
키워드는async
함수 내부에서 사용해야 함
async
함수는async
키워드를 사용해 정의하며 언제나 프로미스를 반환함
- 명시적으로 프로미스를 반환하지 않더라도
async
함수는 암묵적으로 반환값을resolve
하는 프로미스를 반환함
await 키워드
await
키워드는 프로미스가settled
상태(비동기 처리가 수행된 상태)가 될 때까지 대기하다가settled
상태가 되면 프로미스가resolve
한 처리 결과를 반환함
await
키워드는 반드시 프로미스 앞에서 사용해야 함
에러 처리
- 비동기 처리를 위한 콜백 패턴의 단점 중 가장 심각한 것은 에러 처리가 곤란하다는 것임
- 비동기 함수의 콜백함수를 호출한 것이 비동기 함수가 아니기에, 에러 전파가 안됨
- 그러나 async/await는 try.. catch 문을 사용해서 에러 잡아낼 수 있음
async
함수 내에서catch
문을 사용해서 에러 처리를 하지 않으면async
함수는 발생한 에러를reject
하는 프로미스를 반환함
사용 예시
- 여기서 elapsed time이 5000ms 가 나와야 할 것 같지만, 그렇게 되지 않고 test1과 test2는 태스크 큐로 보내짐
- 그래서 console.log가 제일 먼저 뜨고 콜스택이 비워지고 나서 태스크 큐에서 이벤트 루프가 test1과 test2를 실행하게 됨
- async를 쓰는 이유는 결국 그 안에서 await를 사용하기 위함. 근본적으로 async/await는 Promise를 더 편리하게 쓰기 위한것이고 Promise는 콜백 헬을 개선하기 위한 것이니까, 콜백 패턴을 이쁘게 쓰기 위해서 async/await를 쓰는 것이 아닐까
- async를 쓴다고 비동기고 안쓴다고 동기가 아님 자바스크립트에서는. async를 쓰면 Promise를 조금 더 이쁘게 쓸 수 있는 것이지, async function아니더라도 안에서 Promise를 쓰면 비동기로 돌아감