[잘못된 예제]
// 인터넷에서 찾은 왜 for await 를 쓰는 알수 없는 예제..
const render = async function (...urls) {
for await (const url of urls) {
const res = await fetch(url);
const result = await res.json();
console.log(result);
}
// 이런 상황에서는 굳이 for await of 를 안써도 된다
const render = async function (...urls) {
for (const url of urls) {
const res = await fetch(url);
const result = await res.json();
console.log(result);
}
render("<http://localhost:3000/1>", "<http://localhost:3000/2>");
[MDN 예제]
const asyncIterable = {
[Symbol.asyncIterator]() {
return {
i: 0,
next() {
if (this.i < 3) {
return Promise.resolve({ value: this.i++, done: false });
}
return Promise.resolve({ done: true });
}
};
}
};
// next 를 호출하면 Promise 를 반환
(async function() {
for await (let num of asyncIterable) { // resolve 면 진행
console.log(num);
}
})();
// 0
// 1
// 2
[await for of 는 이때 쓰여야 한다]
// Promise를 반환하는 iterable
for await (const res of [Promise.. , Promise,]){
}
// [Symbol.asyncIterator]() 가 존재하는 async iterator 혹은 async generator
for await (const res of asyncIterator){
}
- 일단 실행하면 for of 는 next() 를 호출해서 이터레이터의 값을 받아와서 res에 넣는다
- res 안의 값이 Promise 가 아니면 그냥 바로 루프진행
- res 안의 값이 Promise면 resolve 기다리고
- resolve 되면 안에 Promise 의 resolve 값 들어가고 루프진행
- reject를 던지면 await가 throw error 하고 끝내버린다
[예제]
Promise로 배열
const test = [
new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 2000);
})
.then((res) => res + 1)
.then((res) => res + 1),
new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 2000);
})
.then((res) => res + 2)
.then((res) => res + 2),
new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 2000);
})
.then((res) => res + 3)
.then((res) => res + 3)
];
const testFunc = async () => {
for await (const result of test) {
console.log(result);
}
};
testFunc();
Generator
const test = function* (arr) {
for (const num of arr) {
yield new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 2000);
}).then((res) => res + num).then((res) => res + num);
}
};
const testFunc = async (arr) => {
for await (const result of test(arr)) {
console.log(result);
}
};
testFunc([1, 2, 3]);
Async Generator
const test = async function* (arr) {
for (const num of arr) {
const result = await new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 2000);
});
const result2 = await new Promise((resolve) => {
setTimeout(() => {
resolve(result + num);
}, 2000);
});
const result3 = await new Promise((resolve) => {
setTimeout(() => {
resolve(result2 + num);
}, 2000);
});
yield result3;
}
};
const testFunc = async (arr) => {
for await (const result of test(arr)) {
console.log(result);
}
};
testFunc([1, 2, 3]);
[왜 만든 걸까]
- 순차적으로 Promise 를 반환하는 iterator를 좀 더 깔끔하게 다루려고 만든 듯 하다
// 위에서 다룬 예제
const test = function* (arr) {
for (const num of arr) {
yield new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 2000);
}).then((res) => res + num).then((res) => res + num);
}
};
const testFunc = async (arr) => {
for await (const result of test(arr)) {
console.log(result);
}
};
// for await of 를 안 쓰고 해결
const testFunc = async (arr) => {
for (const promise of test(arr)) {
const result = await promise
console.log(result);
}
};
testFunc([1, 2, 3]);
- 위 의 예제와 달리 일단 루프를 진입한 후 await를 해야해서 다소 깔끔하지 않다