
코드 블록의 실행을 일시 중지했다가 필요한 시점에 재개할 수 있는 특수한 함수
-> 그 외에는 일반 함수와 동일
function* genFunc() {yield 1;}
function * genFunc() {yield 1;}
function *genFunc() {yield 1;}
function*genFunc() {yield 1;}
new genFunc(); // TypeError: genFunc is not a constructor
제너레이터 함수 호출시 제너레이터 객체를 생성해 반환
제너레이터 객체는 이터러블 이면서 이터레이터이다.
이터러블(iterable):
이터러블은 순회 가능한 객체를 나타냅니다. 즉, 이터러블 객체는 내부에 반복 가능한 요소들을 가지고 있고, 이를 순차적으로 접근할 수 있는 객체입니다. 이터러블은 반드시 Symbol.iterator라는 특별한 메서드를 가지고 있어야 합니다. 이 메서드는 이터레이터를 반환해야 합니다.
이터레이터(iterator):
이터레이터는 이터러블 객체를 순회하면서 각 요소에 접근하는 역할을 합니다. 이터레이터는 next() 메서드를 가지고 있으며, 이 메서드를 호출할 때마다 순차적으로 다음 요소에 대한 정보를 반환합니다.
function* genFunc() {yield 1;}
const generator = genFunc();
console.log(Symbol.iterator in generator); // ture
console.log('next' in generator); // true
제너레이터는 yield 키워드와 next 메서드를 통해 실행을 중지 및 재개할 수 있음
next 메서드를 호출하면 함수의 yield 표현식까지만 실행되고 일시 중지됨 -> 이때 함수의 제어권이 호출자로 양도됨
next 메서드를 호출하면 일시 중지된 코드부터 실행을 재개함
function* genFunc() {
yield 1;
yield 2;
yield 3;
}
const generator = genFunc();
console.log(generator.next()); // {value: 1, done: false}
console.log(generator.next()); // {value: 2, done: false}
console.log(generator.next()); // {value: 3, done: false}
console.log(generator.next()); // {value: undefined, done: true}
제너레이터 객체의 next 메서드는 인수 전달 가능
function* genFunc() {
const x = yield 1;
const y = yield (x + 10);
return x + y;
}
const generator = genFunc(0);
let res = generator.next(); // 1은 반환되지만 x에 1이 할당되지는 않음
console.log(res); // {value: 1, done: false}
res = generator.next(10); // x에 10이 할당되고, y에는 값이 할당되지 않고, 20이 반환됨
console.log(res); // {value: 20, done: false}
res = generator.next(20); // y에 20이 할당되고 x+y값으로 30이 반환됨
console.log(res); // {value: 30, done: true}
async/await: 제너레이터보다 간단하고 가독성 좋게 비동기 처리를 동기 처리처럼 동작하도록 구현 가능
프로미스(Promise): 비동기 작업을 처리하고 조작하기 위한 객체
프로미스는 .then() 메서드를 통해 이행 상태에 대한 처리를 등록하고, .catch() 메서드를 통해 거부 상태에 대한 처리를 등록합니다. 또한, .finally() 메서드를 사용하여 이행 또는 거부 여부와 관계없이 항상 실행되는 코드를 추가할 수 있습니다.
프로미스는 여러 개의 프로미스를 조합하고 순차적 또는 병렬로 실행하는 등의 작업도 수행할 수 있어, 비동기 코드를 더 효율적으로 관리할 수 있게 도와줍니다.
await 키워드는 반드시 async 함수 내부에서 사용
async 함수는 항상 프로미스를 반환
async function foo(n) { return n; }
foo(1).then(v => console.log(v)); // 1
클래스의 constructor 메서드는 인스턴스를 반환해야하지만 async 함수는 프로미스를 반환하기 때문에 constructor 메서드는 async 메서드가 될 수 없음
class MyClass {
async constructor() { }
// SyntaxError: Class constructor may not be an async method
}
프로미스가 settled 상태(비동기 처리가 수행된 상태)가 될 때까지 대기하다가 settled 상태가 되면 프로미스가 resolve한 처리 결과를 반환
(1) fetch 함수가 반환한 프로미스가 settled 상태가 될때까지 (1)은 대기
프로미스가 settled 상태가 되면 프로미스가 resolve한 처리 결과가 res 변수에 할당
const fetch = require('node-fetch');
const getGithubUserName = async id => {
const res = await fetch(`https://api.gihub.com/users/${id}`); // (1)
...
};
-> await 키워드는 다음 실행을 일시 중지시켰다가 프로미스가 settled 상태가 되면 재개함
async/await에서 try...catch 문을 사용하여 에러 처리 가능
const fetch = require('node-fetch');
const foo = async() => {
const wrongUrl = 'https://wrong.url';
const response = await fetch(wrongUrl);
const data = await response.json();
return data;
}
foo().then(console.log).catch(console.error); // TypeError: Failed to fetch