바닐라코딩 부트캠프 3주차 과제는 sorting함수 중 몇 가지를 골라 시각화하는 것이었다.
이 과제를 수행하면서 어려웠던 것 중 하나가
"비동기함수를 내가 원하는 시간과 순서대로 실행" 하는 것이었다.
for문을 활용하여 배열안에 담아둔 각각의 정보를 내가 구현한 함수에 전달해서
동기가 아닌 비동기적으로 실행해야 했다.
계속 실패를 하다가 우연히 stackoverflow에서 아래 링크의 글을 발견했다.
(출처 : stackoverflow) JavaScript ES6 promise for loop
이 글에서 보고 내가 과제에 적용했던 부분, 그리고 이해한 내용을 정리하려고 한다.
먼저 코드로 내가 과제에서 구현하고 싶었던 부분은 아래와 같다.
for (let i = 0; i < 10; i++) {
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(i);
}, 1000); // 1초마다 resolve값으로 i가 넘어가서,
})
.then((data) => {
console.log(data); // 0,1,2.. 이런 순서대로 나오겠지?
});
}
반복문 안에 Promise객체를 생성했다.
내 의도는 0 ~ 9까지 1초마다 순차적으로 나오는 것이었다.
그러나 console창에서 실행하면, 1초 뒤 0 ~ 9까지 모두 실행된다.
그 이유는 동기적으로 모든 Promise객체가 생성되었기 때문이다.
for문이 실행되면 초기값 i는 0부터 시작해서, 1씩 증가하면서 총 9번 실행된다.
실행될 때마다 {} 안의 명령문인 new Promise가 실행되어 Promise 객체가 생성된다.
총 9개의 Promise객체가 생성되면서 "1초 뒤 resolve를 실행하라"는 명령문이
setTimeout함수를 통해 예약된다.
그러나 동기적인 작업인 for문이 끝나기 전까지는 Promise는 실행되지 않는다.
즉, for문이 전부 종료되기 전까지 Promise객체
는 pending(대기)
상태로 있다가,
for문이 종료되면
1초 뒤 resolve 함수
를 실행해서 then
으로 i값
을 전달
한다.
따라서 1초 뒤 동시에
console.log(i)
가 실행되는 것이다.
위 코드를 살짝 바꿔 실행해보자.
for (let i = 0; i < 10; i++) {
//pending변수에 promise를 담았다.
const pending = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(i);
}, 1000);
})
.then((data) => {
console.log(data);
});
console.log("pending", pending); //pending값을 확인해보자.
}
peding 변수에 pending(대기)
상태의 Promise객체
가 담겨 있다.
for문이 종료되면 1초 뒤 resolve함수는 then으로 i값을 전달해서, 0 ~ 9의 값이 보여진다.
// 초기값에 i 뿐만 아니라 pending 변수도 함께 작성한다
for (let i = 0, pending = Promise.resolve(); i < 10; i++) { // --- ①
pending // --- ⑤
= pending // --- ⑥
.then(() => { // --- ②
return new Promise((resolve) => {
setTimeout(() => {
resolve(i); // --- ③
}, 1000);
});
})
.then((data) => { // ④
console.log(data);
});
console.log("pending", pending); //pending 값도 체크해보자.
}
for문이 시작되면,
위과 같은 과정으로 loop가 반복된다.
즉, loop가 반복되면서
promise객체
가 생성될 때pending 상태
이지만,
then chain
이 형성되는건loop의 반복 순서 대로
생성되어 있기 때문에
loop
가동기적
으로실행 되는 것처럼
보여진다.
내가 과제를 만들 때 사용했던 for문 + Promise 말고
async await을 쓰면 충분히 가능할 것이다.
(블로그를 쓰다가 발견한 자료인데, 이 자료를 참고하면 Promise.all로도 될 것 같다.
Promises inside a loop - Javascript ES6 )
그러나 Promise로 구현한 덕분에 Promise를 조금이나마 이해할 수 있었다.
지금도 사실 잘 모르는 것 같다.....
ken님 말대로 Promise로 장난질(?)은 더 해봐야 될 것 같다.