생명주기?

(가정) 게시물이 생성되었을때 카테고리는 무조건 선택해야하고 해쉬태그는 선택적으로 해야한다.

 

게시물과 게시물과 카테고리 관계는 같은 생명주기

→ 게시물과 카테고리의 관계는 게시물이 생성될때 같이 생성되고 게시물이 삭제 될때 같이 삭제된다.

 

게시물과 해쉬태그의 관계는 다른 생명주기

 게시물이 생성되었다고 해서 무조건 게시물과 해쉬태그의 관계가 생성되지 않는다.

 

이와 같은 개념으로 src에 있는 routes 에 만들어야할 폴더를 구성해보자.

 

폴더구성을 변경하기 전

├── board
│   ├── board.controller.ts
│   ├── board.module.ts
│   ├── board.service.ts
│   ├── dtos
│   └── functions
├── board_category
│   ├── boardToCategory.module.ts
│   ├── boardToCategory.service.ts
│   └── dto
├── category
│   ├── category.controller.ts
│   ├── category.module.ts
│   ├── category.service.ts
│   └── dto
├── hashtag
│   ├── dto
│   ├── hashtag.controller.ts
│   ├── hashtag.module.ts
│   └── hashtag.service.ts
├── hashtag_board
│   ├── dto
│   ├── hashtagToBoard.controller.ts
│   ├── hashtagToBoard.index.ts
│   ├── hashtagToBoard.module.ts
│   └── hashtagToBoard.service.ts
└── reply
    ├── dto
    ├── reply.controller.ts
    ├── reply.module.ts
    └── reply.service.ts

 

폴더구성을 변경한 후 : board_category 삭제

.
├── board
│   ├── board.controller.ts
│   ├── board.module.ts
│   ├── board.service.ts
│   ├── boardToCategory.service.ts
│   ├── dto
│   └── functions
├── category
│   ├── category.controller.ts
│   ├── category.module.ts
│   ├── category.service.ts
│   └── dto
├── hashtag
│   ├── dto
│   ├── hashtag.controller.ts
│   ├── hashtag.module.ts
│   └── hashtag.service.ts
├── hashtag_board
│   ├── dto
│   ├── hashtagToBoard.controller.ts
│   ├── hashtagToBoard.index.ts
│   ├── hashtagToBoard.module.ts
│   └── hashtagToBoard.service.ts
└── reply
    ├── dto
    ├── reply.controller.ts
    ├── reply.module.ts
    └── reply.service.ts

Promise<void> : 각 작업이 성공적으로 완료되었을 때 추가적인 반환값 없이 완료되는 것을 의미

 

값을 삭제하는 요청처럼 특별하게 반환되는 값이 없을 때 사용

단순히 특정 요청이 완료되는 것을 확인하는 경우 사용

가정:

Category entity에 있는 여러가지  Category를 찾는 서비스를 구현한다

Category 는 Animall, Zoo, IT, Book 가 있다

 

입력 : 

// json
{
	"names" : [ 1, "earth", 3]
}

 

service code

....
async findCategories(findCategoriesRequestDto: FindCategoriesRequestDto): Promise<any> {
    const { ids } = findCategoriesRequestDto;
    const categoryList: number[] = [];
    const results = await Promise.allSettled(ids.map((id) => this.categoryRepository.findOne({ where: { id } })));
    results.forEach((result) => {
      console.log(result)
      categoryList.push(result['value']);
    });
    return categoryList;
  }
...

 

 

콘솔창 출력:

{
  status: 'fulfilled',
  value: Category {
    createdAt: 2024-04-30T07:14:41.809Z,
    updatedAt: 2024-04-30T07:14:41.809Z,
    deletedAt: null,
    id: 1,
    name: 'Animal'
  }
}
{ status: 'fulfilled', value: null }
{
  status: 'fulfilled',
  value: Category {
    createdAt: 2024-04-30T07:14:41.819Z,
    updatedAt: 2024-04-30T07:14:41.819Z,
    deletedAt: null,
    id: 3,
    name: 'IT'
  }
}

  

- entity 에 해당이름이 있던지 없던지 해당 요청은 실행된다.

- entity 에 해당이름이 없는 경우를 처리하려면 vlaue에 접근해서 해야한다. 

 

Promise.all() 은 요청한 것이 모두 성공해야 값을 반환하므로 요청한 모든 값이 필요할 때 사용을 하면 좋다.

 

Promise.allSettled() 은 요청이 성공하던 실패를 하던 모든 값을 반환해준다.

 

코드예시

const urls = [
  'https://api.github.com/users/iliakan',
  'https://api.github.com/users/Violet-Bora-Lee',
  'https://no-such-url'
];

Promise.allSettled(urls.map(url => fetch(url)))
  .then(results => { // (*)
    results.forEach((result, num) => {
      if (result.status == "fulfilled") {
        alert(`${urls[num]}: ${result.value.status}`);
      }
      if (result.status == "rejected") {
        alert(`${urls[num]}: ${result.reason}`);
      }
    });
  });

 

결과

[
  {status: 'fulfilled', value: ...응답...},
  {status: 'fulfilled', value: ...응답...},
  {status: 'rejected', reason: ...에러 객체...}
]

 

스펙에 추가된 지 얼마 안 된 문법이라 지원이 안되면 구현해야한다고 한다.

//https://ko.javascript.info/promise-api#ref-1314
if(!Promise.allSettled) {
  Promise.allSettled = function(promises) {
    return Promise.all(promises.map(p => Promise.resolve(p).then(value => ({
      status: 'fulfilled',
      value
    }), reason => ({
      status: 'rejected',
      reason
    }))));
  };
}

 

 

사용하는 이유 및 상황

 

모든 값이 무조건 다 필요하지 않는 경우.

실패한 경우에 다르게 처리를 해줄 필요가 있는 경우.

    (예시) 한 해쉬태그가 있는지 조회를 했을 때 없는경우 -> 해당 해쉬태그를 등록

 

 

 

참고자료

https://ko.javascript.info/promise-api#ref-1314

 

프라미스 API

 

ko.javascript.info

 

all 안에 주어진 배열에 있는 모든 프로미스를 실행한 후에  그 결과를 배열에 있는 순서대로 반환

배열에 있는 요청 중 하나라도 reject 가 되면  다른 요청의 성공여부에 상관없이 전부 reject

 

코드 예시

//Promise.all( 순회가능한 객체/ 배열 ) 
const promise1 = Promise.resolve("Test Promise.all()");
const promise2 = 5;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
  
// Array ["Test Promise.all()", 5, "foo"]

 

await 를 3개를 사용한 것과 같은 결과를 보여주지만,

좀 더 복잡한 코드를 수행해야할 때는 Promise.all([promise1, ... ]) 이 더 빠르다.

 

사용하는 이유 및 상황

처리속도

만약에 await 를 이용하여 3개의 요청을 실행을 하면 각 요청이 순서대로 실행이된다.

 

하지만, Promise.all()을 이용하여 요청들을 실행하면

Promise.all() 안에 있는 요청들만  병렬로 실행되고 이 요청이 완성될때까지 다른 요청들은 실행 되지 않는다.

이로 인해 요청들을 수행하는데 소요되는 시간이 더 짧아지고 결과를 한꺼번에 처리 가능하다.

-  필요한 요소들을 한꺼번에 처리할 때 유리하다.

 

(사용되는 예시)

게시물을 생성할 때 -> hashtag 정보 검색/ 생성, 카테고리 정보 검색, 새로운 게시물 데이터 생성 필요

-> 3가지를 Promise.all() 을 이용하여 한번에 실행하고 그 결과들을 수집및 처리하여 db에 저장 

 

배열 속의 모든 프로미스의 결과가 필요한 경우

 

'프로그래밍 > JavaScript' 카테고리의 다른 글

[ JS ] 불변객체 immutable object  (1) 2024.05.11
[ JS ] Promise.allSettled 사용하는 이유  (0) 2024.05.06
[ JS ] Promise 설명  (0) 2024.05.05
[ JS ] 정렬 sort( )  (0) 2024.04.13
[JS] call, apply, bind  (0) 2024.03.06

+ Recent posts