promise loop

Eamon·2021년 3월 7일
0

JavaScript

목록 보기
3/8
post-thumbnail

이중 배열의 배열 처리.

이번 미션에서 16 진법으로 string 을 변환 한 값을 배열에 저장하다보니 이중배열 type 의 저장 스타일을 가지게 되었다.

 const array = [
            ["A", "0"],
            ["c", "3"],
            ["1", "3"],
          ];

이런식의 배열을 하나하나 넣어서 비동기로 2초동안 딜레이를 주려고 했더니 막막했다.


첫번째 난관, ForEach

처음에는 forEach loop 를 돌면서 비동기를 제어하려고 했다. map으로 모든 배열을 프라미스객체로 바꾸고 forEach로 바꾸고 loop를 돌리면 될줄 알았으나 forEach라는 녀석은 배열을 한바퀴 돌면서 모두 실행시키기 때문에 순차적인 비동기제어에 알맞지 않다고 생각하였다.

이것 저것 자료를 찾다가 배열을 이용한 promise loop를 만드는 방법이 여러가지가 있을 것 같다는 느낌이 들어서 이것에 대해서 공부해야겠다 라는 생각이 들었다. 그냥 단일 배열 비동기 loop 부터 처리를 할 수 있다면 이중 loop 도 해결 되겠지 라는 마음이였다.

++) async, await 를 이용한 방법도 있지만 promise 문법을 더 익히기 위해서 이 글에서는 다루지 않았다.


1. With for (for 를 사용한 방법)

 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);
            });
}

위 코드는 1초 간격으로 0 부터 9를 출력하는 코드이다.

1) for 를 시작할때 for 안에서 변수 i 와 pending 을 선언한다.

pending 에는 Promise.resolve() 을 집어 넣습니다.

Promise.resolve() 는 Promise를 resolve 된 상태(thenable)로 리턴 하는 것으로 new Promise 와는 차이가 있습니다. 더 자세한 차이를 알고 싶다면 이 링크(new Promise vs Promise.resolve() )를 참고하여 공부해 보시길 바랍니다.

2) pending 에 저장된 promise 객체에 .then 을 추가하여 다음 동작을 추가한다.

3) setTimeout 함수가 1초 뒤 resolve함수를 실행한다.

4) resolve함수에 담겨 있던 i값이 then으로 전달되어 console 로 찍힌다.

5) 4단계 then 실행으로 생성된 Promise객체가 pending 변수에 다시 담긴다.

6) 9 까지 출력한 뒤에 for 문을 끝낸다. ( 비동기 동작 끝낸다. )


2. With reduce(reduce 를 이용한 방법)

[1, 2, 3, 4, 5, 6, 7].reduce( // --- ⑤
  (pending, curr) => 
    pending.then(() => {  // --- ②
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          console.log(curr);// --- ③ 
          resolve();//---④ 
        }, 1000);
      });
    }),
  Promise.resolve() // --- ①
);

이 방법은 좀더 함수형 프로그램에 가까운 코드이다.

우리가 reduce를 기본적으로 쓸 때의 형태는 아래와 같다.

Array.reduce(function(accumulator, currentValue) {} , initialValue);

1) initialValue 를 Promise.resolve() 로 주면서 처음에 accumulator 인 pending 에 thenable 한 promise 객체가 들어가 있게 세팅한다.

2) pending 에 저장된 promise 객체에 .then 을 추가하여 다음 동작을 추가한다.

3) setTimeout 함수가 1초 뒤 curr 에 저장된 배열요소를 console 에 프린트한다.

4) resolve함수를 실행한다.

5) 배열을 모두 돌고 나서 ruduce 함수가 종료된다.


3. for ... of 를 사용하는 방법

const array = [1, 2, 3, 4, 5, 6, 7];

let p = Promise.resolve(); // --- ①

for (let i of array) { // --- ②
  p = p.then( // --- ③ 
    (_) =>
      new Promise((resolve) =>
        setTimeout(function () { 
          console.log(i); // ④
          resolve(); // --- ⑤
        }, 1000)
      )
  );
}

1) p 라는 변수에 Promise.resolve() 를 저장합니다.

2) for ...of 문법으로 array 하나의 요소를 i 로 지정해 줍니다.

3) p에 저장된 promise 객체에 .then 을 추가하여 다음 동작을 추가한다.

4) setTimeout 함수가 1초 뒤 i에 저장된 배열요소를 console 에 프린트한다.

5) resolve함수를 실행한다.



이렇게 세가지 방법의 promise loop 다루는 방법을 알아 보았다. 세가지 방법 모두 loop 를 도는 방법만 약간씩 다를 뿐이지 몇가지 중요한 공통점은 계속 반복되고있다.

  • 첫번째 promise 객체는 Promise.resolve() 를 반환하여 thenable 상태여야한다.
  • then 안의 함수는 promise 객체를 return 해야한다.

특히, 내가 실습할 때 가장 헷갈리고 실수가 많았던 부분이 두 번째 특징이었다.

🔑기억하자🔑


비동기적 흐름을 동기적으로 다루고 싶을때는 then 안에 promise 객체가 반환되어야한다.

참고

JavaScript ES6 promise for loop

for문과 Promise 함께 쓰기

reduce() 를 이용해 순차적으로 프라미스를 해결하는 방법

profile
Steadily , Daily, Academically, Socially semi-nerd Front Engineer.

0개의 댓글