(13) Asynchronous JavaScript - Promise.all() 메소드

반응형

이때까지 하나의 Promise 객체를 다루기 위해 알아야 하기 위해 공부했다.

하지만 실무 개발에서는 여러 개의 Promise 객체를 다뤄야 할 일도 종종 발생하는데,

이번에는 여러 개의 Promise 객체를 다뤄보는 Promise.all 메소드에 대해 araboza.


Promise.all

다음과같이 id 638번부터 642번에 해당하는 데이터를 받아와서 출력하는 코드가 있다.

  // main.js
    async function printList(id) {
    const response = await fetch(`https://todo-api.fesp.shop/api/todolist/${id}`)
    const data = await response.json();
    console.log(data);
    }

for (let i = 638; i < 642 ; i++){
printList(i)
}

이번엔 데이터를 바로바로 출력하는 게 아니라

배열에 저장해 두었다가 모든 데이터가 저장되고 나서 배열을 출력해보자.

 

(함수 바깥에서 값을 받아오려면 await문을 사용해야 한다는 점을 참고)

  // main.js
    async function getList(id) {
    const response = await fetch(`https://todo-api.fesp.shop/api/todolist/${id}`)
    const data = await response.json();
    return data; // data를 반환
    }

for (let i = 638; i < 642 ; i++){
const List = await getList(i) // 함수 바깥에서 값을 받아오기 위해 await 사용
}

그런데 await을 사용하면 getList 함수가 완전히 끝날 때까지 기다린 후에

다음 줄로 넘어가기 때문에,

리퀘스트를 보내고 파싱하는 작업을 순차적으로 하게된다.

이럴 때 바로 Promise.all 메소드를 활용할 수 있으며 

Promise.all은 여러 Promise를 동시에 기다릴 때 사용한다.

 

먼저 promise라는 배열을 만들고

  // main.js
    async function getList(id) {
    const response = await fetch(`https://todo-api.fesp.shop/api/todolist/${id}`)
    const data = await response.json();
    return data; // data를 반환
    }

    const promise = []; // promise 배열 생성
    for (let i = 638; i < 642 ; i++){
        const List = await getList(i) // 함수 바깥에서 값을 받아오기 위해 await 사용
    }

.

getList의 결과를 await하지 않고 바로 배열에 추가한다.

  // main.js
    async function getList(id) {
    const response = await fetch(`https://todo-api.fesp.shop/api/todolist/${id}`)
    const data = await response.json();
    return data; // data를 반환
    }

    const promise = []; // promise 배열 생성

    for (let i = 638; i < 642 ; i++){
      promise.push(getList(i)) // promise 배열에 data를 넣어줌
    }

이렇게 하면 await을 하지 않기 때문에

리퀘시트를 거의 병렬적으로 보내게 된다.

그리고 promise 배열에 추가되는 것은 Promise 객체라는 점도 기억해야한다.

 

마지막으로 promise.all 메소드를 작성한다.

  // main.js
    async function getList(id) {
    const response = await fetch(`https://todo-api.fesp.shop/api/todolist/${id}`)
    const data = await response.json();
    return data; // data를 반환
    }

    const promise = []; // promise 배열 생성

    for (let i = 638; i < 642 ; i++){
      promise.push(getList(i)) // promise 배열에 data를 넣어줌
    }
    Promise.all(promise); // promise.all로 promise 배열을 실행

■ 해석 과정

promise는 Promise 배열이므로 풀어서 작성해보면 [p638, p639 ... p642]으로 볼 수 있는데

처음에는 배열에 있는 Promise들이 모두 Pending 상태일 것이다.

Promise.all 메소드도 Promise를 리턴하는데

처음에는 Pending 상태이다가

아규먼트로 전달된 Promise들이 모두 Fulfilled 상태가 되면

Promise도 Fulfilled 상태가 되고

각 Promise의 성공 결과값들로 이루어진 배열을 성공 결과값으로 갖게된다.

이 예시의 경우 todo데이터로 이루어진 배열이 성공 결과값이 되는 것이다.


반대로 아규먼트로 전달한 Promise 중

하나라도 Rejected 상태가 되면 

Promise도 Rejected 상태가 되고

Rejected된 Promise의 오류를 결과값으로 갖게된다.

 

Promise.all결국 Promise 객체를 리턴하기 때문에

 await이나 then 메소드를 이용할 수 있다.

한번 await으로 사용해보자.

  // main.js
    async function getList(id) {
    const response = await fetch(`https://todo-api.fesp.shop/api/todolist/${id}`)
    const data = await response.json();
    return data; // data를 반환
    }

    const promise = []; // promise 배열 생성

    for (let i = 638; i < 642 ; i++) {
      promise.push(getList(i)) // promise 배열에 data를 넣어줌
    }
    const list = await Promise.all(promise); // await를 사용하여 promise.all로 promise 배열을 실행
    console.log(list);

await을 이용해서 성공 결과값, 즉 todo 배열을 가져왔다.

실행해보면 데이터가 잘 출력되는 것을 확인할 수 있으며

 

또한 다음과 같이 try catch를 이용해서 오류 처리를 할 수도있다.

  // main.js
    async function getList(id) {
    const response = await fetch(`https://todo-api.fesp.shop/api/todolist/${id}`)
    const data = await response.json();
    return data; // data를 반환
    }

    const promise = []; // promise 배열 생성

    for (let i = 638; i < 642 ; i++) {
      promise.push(getList(i)) // promise 배열에 data를 넣어줌
    }

    let list;
    try {
      list = await Promise.all(promise); // await를 사용하여 promise.all로 promise 배열을 실행
    } catch (error) {
      console.error(error);
    }

    console.log(list);

list 변수를 try문 바깥에서도 사용할 수 있도록 try 바깥에서 선언했다.

이렇게 Promise.all 부분에서 오류가 발생하더라도 

try catch문으로 오류처리를 할 수 있다.

 

Promise를 활용하는 비동기 작업 여러 개를 병렬적으로 처리하고 싶을 때는

Promise.all 메소드를 사용하자.

반응형