Bluebird.js

ToastEggsToast·2021년 8월 1일
0

TIL

목록 보기
12/15

Bluebird

Bluebird
npm: https://www.npmjs.com/package/bluebird
Doc: http://bluebirdjs.com/docs/getting-started.html

Bluebird는 Javascript에서 promise를 이행하기 위한 수많은 라이브러리 중 하나입니다.
Javascript에서 사용하는 기존의 promise를 대체해 사용할 수 있는데, 여기서 당연한 의문점이 하나 들 수 있습니다.

이미 Javascript 에서 Promise를 제공하고 있는데, 왜 굳이 이 Bluebird를 사용해야 하는가?

수 많은 해외 유저들이 이와 같은 질문을 남기고 있었고, 저도 기존의 Promise를 대체하는 이 Bluebird 라이브러리가 대체 어째서 인기가 많은지, 왜 사용되고 있는지 궁금했습니다.

왜 Bluebird를 사용해 Promise를 구현하는가

Bluebird Design Principles

  1. Pragmatic and not theoritical - 이론적인 것 대신 실용적인
  2. Fully featured without bloat - 부풀림 없는 완전한 기능 (자바스크립트 비동기 표현력이 뛰어나고, 자바스크립트 어플을 구현하는데 필요한 모든 자바스크립트 기존 유틸리티 기능과 조합성을 제공.)
  3. Easy to debug - 디버그 용이성
  4. Zero overhead abstraction - 제로 오버헤드 추상화 (사용자가 서버 측 성능에 구애받지 않을 수 있도록 Promise 구현의 성능을 Bluebird에서 제어함)
  5. Runs everywhere - 모든 곳에서 실행 (IE, Chrome 등 환경에 구애받지 않고 사용, 호환이 가능함)
  6. Spec compatible - 사양 호환 (기존의 자바스크립트 Promise와의 호환)

Bluebird를 이용하면 Native Promise 혹은 async/await 보다 빠르게 비동기 처리를 할 수 있도록 도와줍니다.

해당 블로그에서 각 node의 환경에서 Bluebird Promise, Native Promise, Async/await 을 사용했을 경우의 퍼포먼스 결과 그래프를 보여주고 있는데, 해당 블로그에서 보여주는 그래프를 보면 속도적인 측면, 메모리 관리 측면에서 Bluebird를 사용하는 것이 더 효율적이라는 그래프를 보여주고 있습니다.

Bluebird를 이용해 서버 측 클라이언트를 제작하게 되면, rejection 등을 통해 좀 더 쉽게 error handling 이 가능합니다.

Bluebird 사용 예시 (with. map)

import Bluebird from 'bluebird';

 await Bluebird.map(args.deletedBands, async (db) => {
          const deletedUserTicket = await UserTicketModel.findOne({
            uid: db.ticketUid,
          });

          if (!deletedUserTicket) {
            throw new Error(
              `취소하려는 ${db.ticketUid}는 존재하지 않는 티켓입니다. 확인 후 다시 시도해주세요.`
            );
          }

          deletedUserTicket.status = UserTicketStatus.Cancelled;
          deletedUserTicket.save();

          const deletedBand = await BandModel.findOne({
            nfcId: db.bandNfcId,
            status: BandStatus.InUse,
          });

          if (!deletedBand) {
            throw new Error(
              `취소하려는 ${db.bandNfcId}는 등록되지 않았거나, 사용 중이지 않은 밴드입니다. 확인 후 다시 시도해주세요.`
            );
          }

          await BandModel.updateOne(
            { _id: deletedBand._id },
            {
              $set: { status: BandStatus.Idle },
              $unset: { userTicket: '', user: '' },
            }
          ); 

          return deletedUserTicket._id;
        })
          .then(async (deletedTickets) => {
            const order = await OrderModel.findOne({ uid: args.orderUid });

            const orderTickets = differenceWith(
              order?.userTickets,
              deletedTickets,
              isEqual
            );

            await OrderModel.updateOne(
              { uid: args.orderUid },
              {
                $set: { userTickets: orderTickets },
              }
            );
          })
          .then(async () => {
            const order = await OrderModel.findOne({ uid: args.orderUid });
            await order?.recalculate();

            return order;
          });

Bluebird를 사용할 경우, 한 번에 처리시킬 task의 갯수를 지정해줄 수 있습니다.
예를 들어 Bluebird.map(arr, (el)=>{ }, { concurrency: 1 }) 과 같이 concurrency를 기재해 줄 경우, 한 번에 1개의 작업만 처리할 수 있도록 동작합니다.

profile
개발하는 반숙계란 / 하고싶은 공부를 합니다. 목적은 흥미입니다.

0개의 댓글