iterator/generator와 async/await비교

2018-11-23

ES8부터 도입된 async/await는 iterator/generator로 부터 파생되었다.
async/await의 사용하기 전에 iterator/generator부터 알아보자!

iterator

내부적으로 반복처리
[Symbol.iterator] 반복되는 규칙을 내부적으로 처리하는 것을 만드는 부분

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//피보나치 수열 예제
let fibonacci = {
maxStep: 20,
[Symbol.iterator]() {
let pre = 0, cur = 1, step = 0, maxStep = this.maxStep;
return {
next() {
[pre, cur] = [cur, pre + cur];
return {done: step ++ >= maxStep, value: cur} //상태값과 value를 리턴해줌
}
}
}
}


for (let n of fibonacci) {
console.log(n) // 1,2,3,5,8,13,21,34 ....
}

generator

generator는 iterator의 특징이자 단점인 무한 반복을 해결해준다.
next해서 접근 가능 하며 기존의 {done, value}를 자동으로 리턴해준다.
사용법은 function앞에 (반복기)을 붙이고 yield는 value를 정해준다.
yield가 있는 시점에서 함수의 실행을멈추며 yield
도 가능하다(문자열, 배열, 다른 반복기 값 가능)

1
2
3
4
5
6
7
8
9
10
11
12
13
function * factorialGenerator() {
let cur = 1;
let count = 1;
while(true) {
[count, cur] = [count + 1, cur * count]
yield cur;
}
}


const factorial = factorialGenerator();
factorial.next().value // 1
factorial.next().value // 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let myObj = {};
myObj[Symbol.iterator] = function* () {
yield "1"; //단일 값이 전달
yield* [2,3]; //yield* 로 값을 반환하면 --> 해당 값이 다시 하나의 iterator로 취급되어 내부루프 처리하듯 순서대로 처리함 //배열
yield* "45"; //문자열
yield* innerGenerator(); //다른 반복기 값
yield "9";
}

function* innerGenerator() {
yield 6;
yield* new Set(["7", "8"]);
}

console.log([...myObj]) // ["1", 2, 3, "4", "5", 6, "7", "8", "9"]

async/await

비동기를 동기처럼 보이게 한다. try, catch문을 사용해한다.
기존의 * => async, yield => await로 바뀐다.

아래 코드는 async/await로 작성하는게 generator로 코드를 짜는것 보다 훨씬 가독성도 높고 코드가 간단하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function getUser() {
return new Promise((resolve, reject) => {
resolve('test');
})
}

function* generator() {
const users = yield getUser();
console.log("user", users)
return users;
}

const iterator = generator();
const iteration = iterator.next();//generator함수 실행

iteration.value.then(
resolve => {
const nextIteration = iterator.next(resolve);
nextIteration;
}
)

1
2
3
4
5
6
7
8
9
10
11
12
13
function getUser() {
return new Promise((resolve, reject) => {
resolve('test');
})
}

async function generator2() {
const users = await getUser();
console.log(users)
return users;
}

generator2();