코드 블록의 실행을 필요한 시점에 일시중지 했다가 필요한 시점에 재개 할수 있는 특수한 함수
▫️함수 호출자가 함수 실행을 일시중지시키거나 재개 할수 있음 (제어가능 )
▫️함수 호출자와 양방향으로 함수의 상태를 주고 받을 수 있다.
▫️제너레이터 함수를 호출 함수 코드를 실행하는것이 아니라 이터러블 하면서 동시에 이터레이터인 제너레이터 객체를 반환
▫️함수 호출자는 next 메소드를 이용해 yield 표현식까지 함수를 실행시켜 제너레이터 객체가 관리하는 상태를 꺼내올수있고, 인수를 전달해서 제너레이터 객체에 상태를 밀어 넣을수있다.
▫️제어권이 함수에게 넘어가고 함수 코드를 한번에 실행
▫️매개변수를 통해 함수 외부에서 값을 주입받고 함수코드를 일괄실행하여 결과값을 함수 외부로 반환
▫️함수 코드를 일괄 실행하고 값을 반환
- 이터러블 이면서 동시에 이터레이터 의 의미
> 자바스크립트에서 **반복 가능한 데이터 구조**를 다룰 때 자주 등장하는 개념, 이들은 서로 밀접하게 관련되어 있지만, 서로 다른 역할을 함
>
### **1. 이터러블 (Iterable)**
- 반복가능한 객체 , 즉 데이터를 하나씩 순차적으로 접근할수 있는 객체
- for of 문을 사용하여 이터러블 객체를 순회할수 있음.
- ex) **배열**, **문자열**, **Map**, **Set**
- 이터러블 객체는 반드시 `Symbol.iterator` 메서드를 가지고 있어야 함 이 메서드는 **이터레이터 객체**를 반환
### **2. 이터레이터 (Iterator)**
- **이터러블 객체를 순차적으로 순회할 수 있는 객체**
- 이터레이터는 `next()` 메서드를 제공하며, 이 메서드를 호출할 때마다 이터러블 객체에서 **다음 값을 반환 , 다음값이 없으면** `done`이 `true`인 결과를 반환
- 이터레이터 객체는 `{ value, done }` 형태의 객체를 반환합니다.
- **`value`**: 현재 항목의 값.
- **`done`**: 순회가 끝났는지를 나타내는 Boolean 값. `done: true`는 더 이상 값이 없다는 뜻
▫️제너레이터 함수는 function 키워드로 선언하고, 하나이상의 yield 표현식을 포함함
▫️제너레이터는 화살표 함수로 정의할수 없다
▫️new연산자와함께 생성자 함수로 호출할수 없다.
function* count(num) { //애스터 리스크를 function 과 함수 이름 사이
let count = 1;
while (count <= num) {
yield count; //yield: 제너레이터 함수 내에서 값을 반환할 때 사용, 함수실행을 멈춤
count++;
}
}
const test = count(3);
console.log(test.next()); // { value: 1, done: false }
//next(): 제너레이터 함수의 실행을 한 단계 진행시킬 때 사용, 두가지 값 반환
console.log(test.next()); // { value: 2, done: false }
console.log(test.next()); // { value: 3, done: false }
console.log(test.next()); // { value: undefined, done: true }
//value: yield로 반환된 값.
//done: 제너레이터 함수가 끝났는지 여부를 나타내는 Boolean 값.
yield 표현식은 제너레이터(generator) 함수 내에서 사용되는 특별한 키워드로, 함수의 실행을 일시 중단하고 값을 반환하거나, 다시 시작할 때 어떤 값을 전달할 수 있게 함 .yield는 제너레이터 함수에서만 사용할 수 있음.▫️제너레이터 함수는 이터러블이면서 동시에 이터레이터한 제너레이터 객체를 생성해 반환한다.
▫️제너레이터 객체는 next 메소드를 가지는 이터레이터 이므로 심볼, 이터레이터 메서드를 호출해서 별도로 이터레이터를 생성할 필요가 없다.
▫️제너레이터 객체는 이터레이터에는 없는 return, throw 메소드를 갖는다.
{ value: yield된 값 , done: false }된 값을 반환 , 인수를 전달 할수있다{ value: 인수로 전달받은 값, done: true } 의 이터레이터 리절트 객체를 반환한다.{ value: undefined, done: true } 를 값으로 갖는 이터레이터 리절트 객체를 반환function* count(max) {
let count = 1;
while (count <= max) {
yield count;
count++;
}
}
const test = count(3);
console.log(test.next()); // { value: 1, done: false }
console.log(test.next()); // { value: 2, done: false }
console.log(test.next()); // { value: 3, done: false }
console.log(test.next()); // { value: undefined, done: true }
제너레이터 함수안에 yield 키워드 사용
next () 호출
제너레이터 함수에서 yield 를 사용해 promise 가 완료되기를 대기하고, next() 가 호출되면 그 다음 값을 반환
즉, 후속처리 메소드없이 비동기 처리결과를 반환하도록 구현가능하다.
//제너레이터 생성
function test() {
return (function* () { //1. test 는 제너레이터를 반환
console.log('첫번째')
// 첫 번째 Promise 완료 대기
const result1 = yield new Promise((resolve) =>
setTimeout(() => resolve("Result 1"), 1000)
);
console.log("두번째:", result1);
// 두 번째 Promise 완료 대기
const result2 = yield new Promise((resolve) =>
setTimeout(() => resolve("Result 2"), 1000)
);
console.log("세번째:", result2);
return "끝";
})();
}
{value: yield 값 , done: true or false}
// 제너레이터 실행
async function run(generator) {
//2. run 함수는 제너레이터를 실행하면서 yield에서 반환된 Promise를 기다림
const iterator = generator();
let result = iterator.next();
//3. 각 Promise가 완료시 결과를 next() 메서드에 전달,다음 단계를 실행
while (!result.done) {
const promise = result.value;
result = iterator.next(await promise); // Promise 결과를 다음 next()로 전달
}
return result.value; // 제너레이터 종료 시 최종 반환값
}
// 실행
run(test)
.then((finalResult) =>
console.log("네번째:", finalResult)
//4. 마지막 단계에서는 제너레이터가 종료되며 최종 결과("Done")를 반환합니다.
);
//결과
첫번째
두번째 : Result 1
세번째 : Result 2
네번째 : 끝
▫️es8 부터는 async/await이 도입되어 제너레이터 보다 간단하고 가독성좋게 비동기 처리를 구현할수 있다.
try…catch 문을 사용해서 에러를 처리, 콜백함수를 전달받는 비동기 함수와 달리promise를 반환 하는 비동기 함수는 명시적으로 호출할수 있기 때문에 호출자가 명확
async 함수 내 에서 catch 문을 사용하지 않으면 발생한 에러를 reject 하는 promise를 반환하기 때문에, 함수내부가 아니라 함수 호출 후 후속처리 메소드를 사용해서 에러를 catch 할 수도있다.