# React 프로젝트에서 Promise.allSettled 활용하기

### Promise.all

프론트엔드에서 여러 개의 네트워크 요청을 처리할 때 Promise.all 또는 Promise.allSettled 메소드를 활용하여 동시에 처리할 수 있다.

Promise.all 메소드는 프로미스 배열을 인자로 받아서 하나의 프로미스를 반환하는데 이 프로미스가 이행(fulfill)되면 인자에 있던 각 프로미스의 결과 값을 배열 형태로 받을 수 있다.

* 다음과 같은 상황에는 콘솔에 \[1, 2, 3\]이 출력된다.
    

```typescript
const resolvedAll = await Promise.all([
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.resolve(3),
]);
console.log(resolvedAll);
```

* 첫번째 fetchApis 함수는 각각의 요청을 async, await으로 순서대로 처리하기 때문에 시간이 오래 걸린다.
    
* 두번째 fetchApis 함수는 Promise.all 메소드로 소요 시간을 단축시킬 수 있다.
    

```typescript
const App = () => {
  const fetchApis = useCallback(async () => {
    const resp1 = await fetchApi1(args1);
    const resp2 = await fetchApi2(args2);
    const resp3 = await fetchApi3(args3);
    return [resp1, resp2, resp3];
  }, []);

  const fetchApis = useCallback(async () => {
    const responses = await Promise.all(
      fetchApi1(args1),
      fetchApi2(args2),
      fetchApi3(args3)
    );
  }, []);
};
```

Promise.all 메소드는 각각의 작업 중 하나라도 작업이 거부(reject)되면 아무것도 반환되지 않는다. 이때 메소드가 반환한 프로미스의 거부 사유는 첫번째 프로미스와 같다.

다음 상황에서 첫번째로 거부되는 프로미스는 `Promise.reject(1)`로, 콘솔에는 1이 출력된다.

```typescript
try {
  const result = await Promise.all([
    Promise.reject(1),
    Promise.reject(2),
    Promise.reject(3),
    Promise.reject(4),
  ]);
} catch (error) {
  console.log(error);
}
```

### Promise.allSettled

Promise.allSettled 메소드는 프로미스 배열을 받아서 하나의 프로미스를 반환한다는 것은 Promise.all과 같으나, 프로미스가 이행되면 인자로 주어진 배열의 각 프로미스에 대해 이행된 결과를 나타내는 배열을 받을 수 있다.

메소드가 반환한 프로미스가 이행되었을 때 각 요소는 다음과 같은 타입을 나타낸다.

* 공통적으로 status라는 속성이 존재한다.
    
* 이행되면 value로 각각의 프로미스가 이행된 값을 확인할 수 있다.
    
* 거부된 프로미스는 reason으로 거부된 사유를 파악할 수 있다.
    

```typescript
interface PromiseFulfilledResult<T> {
  status: "fulfilled";
  value: T;
}

interface PromiseRejectedResult {
  status: "rejected";
  reason: any;
}

type PromiseSettledResult<T> =
  | PromiseFulfilledResult<T>
  | PromiseRejectedResult;
```

프로젝트에서 Promise.allSettled 메소드를 적용할 때에는 이행된 결과만 필터링하는 작업이 필요했다.

* 첫번째 예시처럼 `filter` 메소드로 필터링만 하거나
    
* 두번째 처럼 `reduce` 메소드로 반환값을 토대로 추가 작업을 할 수 있었다.
    

```typescript
const responses = await Promise.allSettled([
  Promise.resolve(0),
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.reject("REJECT 1"),
  Promise.reject("REJECT 2"),
  Promise.resolve(true),
  Promise.resolve(false),
]);
const fulfilledAll = responses.filter(
  (response) => response.status === "fulfilled"
);
```

```typescript
const responses = await Promise.allSettled([
  fetchApi(0),
  fetchApi(1),
  fetchApi(2),
  fetchApi(3),
  fetchApi(4),
]);
const projects = responses.reduce((reduced, response) => {
  if (response.status === "rejected") {
    return reduced;
  }
  const id = createIdFromResponse(response);
  reduced = reduced.concat({
    id,
    ...response,
  });
  return reduced;
}, []);
```
