p-limit vs async vs bluebird vs promise-limit vs promise-queue
비동기 처리 및 프로미스 제어
p-limitasyncbluebirdpromise-limitpromise-queue유사 패키지:

비동기 처리 및 프로미스 제어

비동기 처리 및 프로미스 제어 라이브러리는 JavaScript에서 비동기 작업을 효율적으로 관리하고 제어하는 데 도움을 주는 도구입니다. 이러한 라이브러리는 비동기 함수의 실행 순서를 제어하거나, 동시에 실행되는 비동기 작업의 수를 제한하거나, 프로미스 체인을 더 쉽게 다룰 수 있도록 다양한 기능을 제공합니다. 예를 들어, async는 비동기 작업을 순차적, 병렬적으로 처리할 수 있는 다양한 유틸리티 함수를 제공하며, bluebird는 고성능 프로미스 구현체로, 프로미스 체인, 병렬 처리, 에러 핸들링 등을 효율적으로 지원합니다. p-limit와 promise-limit는 동시에 실행되는 프로미스의 수를 제한하여 리소스 사용을 최적화하는 데 유용하며, promise-queue는 프로미스를 큐에 넣고 순차적으로 처리하는 기능을 제공합니다.

npm 다운로드 트렌드

3 년

통계 세부사항

패키지
다운로드
Stars
크기
Issues
발행일
라이선스
p-limit442,781,588-16.1 kB-2ヶ月前MIT
async144,003,447-808 kB-2年前MIT
bluebird81,732,477---7年前MIT
promise-limit8,512,829---8年前ISC
promise-queue1,235,228---9年前MIT

기능 비교: p-limit vs async vs bluebird vs promise-limit vs promise-queue

비동기 작업 처리 방식

  • p-limit:

    p-limit는 동시에 실행되는 프로미스의 수를 제한하는 간단한 함수입니다. 이 함수를 사용하여 리소스 사용을 최적화하고, 과도한 비동기 작업으로 인한 성능 저하를 방지할 수 있습니다. 예를 들어, 웹 스크래핑이나 API 호출 시 동시에 실행되는 요청의 수를 제한하여 서버에 부담을 줄일 수 있습니다.

  • async:

    async는 비동기 작업을 순차적, 병렬적, 제한적 방식으로 처리할 수 있는 다양한 유틸리티 함수를 제공합니다. 예를 들어, async.series는 작업을 순차적으로 실행하고, async.parallel은 작업을 병렬로 실행합니다. 또한, async.eachLimit와 같은 함수를 사용하여 동시에 실행되는 작업의 수를 제한할 수 있습니다.

  • bluebird:

    bluebird는 프로미스 기반의 비동기 작업 처리에 특화된 라이브러리로, 프로미스 체인, 병렬 처리, 에러 핸들링 등을 효율적으로 지원합니다. Promise.all, Promise.race, Promise.map 등의 메서드를 제공하여 여러 프로미스를 동시에 처리하거나, 특정 작업을 병렬로 실행할 수 있습니다.

  • promise-limit:

    promise-limit은 비슷한 기능을 제공하지만, 더 간단한 API를 통해 동시에 실행되는 프로미스의 수를 제한합니다. 이 라이브러리는 코드의 복잡성을 줄이고, 빠르게 구현할 수 있는 장점이 있습니다.

  • promise-queue:

    promise-queue는 프로미스를 큐에 넣고 순차적으로 처리하는 기능을 제공합니다. 이 큐는 FIFO(선입선출) 방식으로 작동하며, 각 프로미스가 완료된 후 다음 프로미스가 실행됩니다. 이를 통해 비동기 작업의 순서를 보장하고, 리소스 사용을 효율적으로 관리할 수 있습니다.

동시 실행 제한

  • p-limit:

    p-limit는 동시 실행되는 프로미스의 수를 간단하게 제한하는 데 특화된 라이브러리입니다. 이 라이브러리는 비동기 작업의 동시 실행을 제어하여 리소스 사용을 최적화하고, 과도한 비동기 작업으로 인한 성능 저하를 방지합니다.

  • async:

    async는 동시 실행을 제한하는 기능을 제공하지만, 이를 구현하기 위해서는 추가적인 설정이 필요합니다. 예를 들어, async.eachLimit 함수를 사용하여 동시에 실행되는 작업의 수를 제한할 수 있습니다.

  • bluebird:

    bluebird는 프로미스의 동시 실행을 제한하는 기능을 제공하며, Promise.map 메서드에서 concurrency 옵션을 사용하여 동시 실행되는 프로미스의 수를 제한할 수 있습니다.

  • promise-limit:

    promise-limit은 동시 실행 제한 기능을 제공하며, 간단한 API를 통해 쉽게 사용할 수 있습니다. 이 라이브러리는 동시 실행되는 프로미스의 수를 제한하여 리소스 사용을 효율적으로 관리할 수 있습니다.

  • promise-queue:

    promise-queue는 프로미스를 큐에 넣고 순차적으로 처리하므로, 동시 실행되는 작업이 없으며, 각 작업이 완료된 후 다음 작업이 실행됩니다. 이를 통해 리소스 사용을 효율적으로 관리하고, 작업의 순서를 보장할 수 있습니다.

에러 핸들링

  • p-limit:

    p-limit는 에러 핸들링 기능을 제공하지 않지만, 동시 실행되는 프로미스의 수를 제한하는 동안 발생하는 에러는 일반적인 프로미스 에러 핸들링 방식으로 처리할 수 있습니다.

  • async:

    async는 비동기 작업에서 발생하는 에러를 처리하기 위한 다양한 메커니즘을 제공합니다. 예를 들어, async.series나 async.parallel과 같은 함수는 콜백 함수의 첫 번째 인자로 에러를 전달하여 에러 핸들링을 할 수 있습니다.

  • bluebird:

    bluebird는 프로미스 기반의 에러 핸들링에 강력한 기능을 제공합니다. catch, finally, spread 등의 메서드를 사용하여 프로미스 체인에서 발생하는 에러를 효과적으로 처리할 수 있습니다.

  • promise-limit:

    promise-limit은 에러 핸들링 기능을 제공하지 않지만, 동시 실행 제한 중 발생하는 에러는 프로미스의 기본 에러 핸들링 메커니즘을 통해 처리할 수 있습니다.

  • promise-queue:

    promise-queue는 큐에 있는 프로미스가 실패할 경우, 해당 프로미스의 에러를 처리할 수 있는 콜백 함수를 등록할 수 있습니다. 그러나 기본적으로 에러 핸들링 기능은 제공하지 않으며, 사용자가 직접 구현해야 합니다.

코드 예제

  • p-limit:

    동시 실행 수를 제한하는 예제

    const pLimit = require('p-limit');
    
    const limit = pLimit(2); // 동시에 실행할 프로미스 수를 2로 제한
    
    const tasks = [
      () => new Promise((resolve) => setTimeout(() => resolve('Task 1 완료'), 1000)),
      () => new Promise((resolve) => setTimeout(() => resolve('Task 2 완료'), 500)),
      () => new Promise((resolve) => setTimeout(() => resolve('Task 3 완료'), 2000)),
      () => new Promise((resolve) => setTimeout(() => resolve('Task 4 완료'), 1500)),
      () => new Promise((resolve) => setTimeout(() => resolve('Task 5 완료'), 800)),
    ];
    
    const limitedTasks = tasks.map((task) => limit(task));
    
    Promise.all(limitedTasks)
      .then((results) => {
        console.log('모든 작업 완료:', results);
      })
      .catch((err) => {
        console.error('에러 발생:', err);
      });
    
  • async:

    비동기 작업을 순차적으로 처리하는 예제

    const async = require('async');
    
    const tasks = [
      (callback) => setTimeout(() => callback(null, 'Task 1 완료'), 1000),
      (callback) => setTimeout(() => callback(null, 'Task 2 완료'), 500),
      (callback) => setTimeout(() => callback(null, 'Task 3 완료'), 2000),
    ];
    
    async.series(tasks, (err, results) => {
      if (err) {
        console.error('에러 발생:', err);
      } else {
        console.log('모든 작업 완료:', results);
      }
    });
    

    비동기 작업을 병렬로 처리하는 예제

    const async = require('async');
    
    const tasks = [
      (callback) => setTimeout(() => callback(null, 'Task 1 완료'), 1000),
      (callback) => setTimeout(() => callback(null, 'Task 2 완료'), 500),
      (callback) => setTimeout(() => callback(null, 'Task 3 완료'), 2000),
    ];
    
    async.parallel(tasks, (err, results) => {
      if (err) {
        console.error('에러 발생:', err);
      } else {
        console.log('모든 작업 완료:', results);
      }
    });
    

    동시 실행 수를 제한하는 예제

    const async = require('async');
    
    const tasks = [
      (callback) => setTimeout(() => callback(null, 'Task 1 완료'), 1000),
      (callback) => setTimeout(() => callback(null, 'Task 2 완료'), 500),
      (callback) => setTimeout(() => callback(null, 'Task 3 완료'), 2000),
      (callback) => setTimeout(() => callback(null, 'Task 4 완료'), 1500),
      (callback) => setTimeout(() => callback(null, 'Task 5 완료'), 800),
    ];
    
    async.eachLimit(tasks, 2, (task, callback) => {
      task(callback);
    }, (err) => {
      if (err) {
        console.error('에러 발생:', err);
      } else {
        console.log('모든 작업 완료');
      }
    });
    
  • bluebird:

    프로미스를 사용한 병렬 처리 예제

    const Promise = require('bluebird');
    
    const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    
    const tasks = [
      () => delay(1000).then(() => 'Task 1 완료'),
      () => delay(500).then(() => 'Task 2 완료'),
      () => delay(2000).then(() => 'Task 3 완료'),
    ];
    
    Promise.all(tasks.map((task) => task()))
      .then((results) => {
        console.log('모든 작업 완료:', results);
      })
      .catch((err) => {
        console.error('에러 발생:', err);
      });
    

    동시 실행 수를 제한하는 예제

    const Promise = require('bluebird');
    
    const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    
    const tasks = [
      () => delay(1000).then(() => 'Task 1 완료'),
      () => delay(500).then(() => 'Task 2 완료'),
      () => delay(2000).then(() => 'Task 3 완료'),
      () => delay(1500).then(() => 'Task 4 완료'),
      () => delay(800).then(() => 'Task 5 완료'),
    ];
    
    Promise.map(tasks, (task) => task(), { concurrency: 2 })
      .then((results) => {
        console.log('모든 작업 완료:', results);
      })
      .catch((err) => {
        console.error('에러 발생:', err);
      });
    
  • promise-limit:

    동시 실행 수를 제한하는 예제

    const promiseLimit = require('promise-limit');
    
    const limit = promiseLimit(2); // 동시에 실행할 프로미스 수를 2로 제한
    
    const tasks = [
      () => new Promise((resolve) => setTimeout(() => resolve('Task 1 완료'), 1000)),
      () => new Promise((resolve) => setTimeout(() => resolve('Task 2 완료'), 500)),
      () => new Promise((resolve) => setTimeout(() => resolve('Task 3 완료'), 2000)),
      () => new Promise((resolve) => setTimeout(() => resolve('Task 4 완료'), 1500)),
      () => new Promise((resolve) => setTimeout(() => resolve('Task 5 완료'), 800)),
    ];
    
    const limitedTasks = tasks.map((task) => limit(task));
    
    Promise.all(limitedTasks)
      .then((results) => {
        console.log('모든 작업 완료:', results);
      })
      .catch((err) => {
        console.error('에러 발생:', err);
      });
    
  • promise-queue:

    프로미스를 큐에 넣고 순차적으로 처리하는 예제

    const PromiseQueue = require('promise-queue');
    
    const queue = new PromiseQueue(1, Infinity); // 동시 실행 수 1, 큐 크기 무제한
    
    const tasks = [
      () => new Promise((resolve) => setTimeout(() => resolve('Task 1 완료'), 1000)),
      () => new Promise((resolve) => setTimeout(() => resolve('Task 2 완료'), 500)),
      () => new Promise((resolve) => setTimeout(() => resolve('Task 3 완료'), 2000)),
    ];
    
    tasks.forEach((task) => {
      queue.add(task).then((result) => console.log(result));
    });
    

리소스 사용 최적화

  • p-limit:

    p-limit는 동시 실행되는 프로미스의 수를 제한하여 리소스 사용을 최적화하는 데 특화된 라이브러리입니다. 이 라이브러리를 사용하면, 과도한 비동기 작업으로 인한 리소스 고갈을 방지하고, 시스템의 안정성을 높일 수 있습니다.

  • async:

    async는 비동기 작업을 효율적으로 처리할 수 있는 다양한 도구를 제공하지만, 리소스 사용을 최적화하기 위해서는 개발자가 동시 실행 수를 적절히 조절해야 합니다.

  • bluebird:

    bluebird는 프로미스 기반의 비동기 작업 처리에 최적화된 라이브러리로, 리소스 사용을 효율적으로 관리할 수 있는 다양한 기능을 제공합니다. 특히, Promise.map 메서드에서 concurrency 옵션을 사용하여 동시 실행되는 프로미스의 수를 제한할 수 있어, 리소스 사용을 최적화할 수 있습니다.

  • promise-limit:

    promise-limit은 비슷한 기능을 제공하지만, 더 간단한 API를 통해 리소스 사용을 효율적으로 관리할 수 있습니다. 이 라이브러리는 동시 실행되는 프로미스의 수를 제한하여, 리소스 사용을 최적화하고, 시스템의 안정성을 높이는 데 도움을 줍니다.

  • promise-queue:

    promise-queue는 프로미스를 큐에 넣고 순차적으로 처리하므로, 리소스 사용을 효율적으로 관리할 수 있습니다. 동시 실행 수가 1로 제한되기 때문에, 한 번에 하나의 작업만 실행되어 리소스 사용이 안정적입니다.

선택 방법: p-limit vs async vs bluebird vs promise-limit vs promise-queue

  • p-limit:

    p-limit를 선택하세요. 동시에 실행되는 프로미스의 수를 간단하게 제한하고, 코드의 복잡성을 최소화하면서 리소스 사용을 최적화하고 싶을 때.

  • async:

    async를 선택하세요. 비동기 작업을 더 유연하게 관리하고, 다양한 패턴(예: 시퀀스, 병렬, 제한 등)을 지원하는 기능이 필요할 때.

  • bluebird:

    bluebird를 선택하세요. 고성능 프로미스 구현체가 필요하고, 프로미스 체인, 에러 핸들링, 병렬 처리 등에서 더 많은 기능과 최적화를 원할 때.

  • promise-limit:

    promise-limit을 선택하세요. p-limit와 유사하지만, 더 간단한 API를 제공하여 빠르게 구현하고 싶을 때.

  • promise-queue:

    promise-queue를 선택하세요. 프로미스를 큐에 넣고 순차적으로 처리해야 하며, 작업의 순서를 보장하고 싶을 때.

p-limit의 README

p-limit

Run multiple promise-returning & async functions with limited concurrency

Works in Node.js and browsers.

Install

npm install p-limit

Usage

import pLimit from 'p-limit';

const limit = pLimit(1);

const input = [
	limit(() => fetchSomething('foo')),
	limit(() => fetchSomething('bar')),
	limit(() => doSomething())
];

// Only one promise is run at once
const result = await Promise.all(input);
console.log(result);

API

pLimit(concurrency) default export

Returns a limit function.

concurrency

Type: number | object
Minimum: 1

Concurrency limit.

You can pass a number or an options object with a concurrency property.

rejectOnClear

Type: boolean
Default: false

Reject pending promises with an AbortError when clearQueue() is called. This is recommended if you await the returned promises, for example with Promise.all, so pending tasks do not remain unresolved after clearQueue().

import pLimit from 'p-limit';

const limit = pLimit({concurrency: 1});

limit(fn, ...args)

Returns the promise returned by calling fn(...args).

fn

Type: Function

Promise-returning/async function.

args

Any arguments to pass through to fn.

Support for passing arguments on to the fn is provided in order to be able to avoid creating unnecessary closures. You probably don't need this optimization unless you're pushing a lot of functions.

Warning: Avoid calling the same limit function inside a function that is already limited by it. This can create a deadlock where inner tasks never run. Use a separate limiter for inner tasks.

limit.map(iterable, mapperFunction)

Process an iterable of inputs with limited concurrency.

The mapper function receives the item value and its index.

Returns a promise equivalent to Promise.all(Array.from(iterable, (item, index) => limit(mapperFunction, item, index))).

If the iterable throws during iteration, the returned promise rejects with that error. Mapper functions that were already scheduled still run, and their results are discarded.

This is a convenience function for processing inputs that arrive in batches. For more complex use cases, see p-map.

limit.activeCount

The number of promises that are currently running.

limit.pendingCount

The number of promises that are waiting to run (i.e. their internal fn was not called yet).

limit.clearQueue()

Discard pending promises that are waiting to run.

This might be useful if you want to tear down the queue at the end of your program's lifecycle or discard any function calls referencing an intermediary state of your app.

Note: This does not cancel promises that are already running.

When rejectOnClear is enabled, pending promises are rejected with an AbortError. This is recommended if you await the returned promises, for example with Promise.all, so pending tasks do not remain unresolved after clearQueue().

limit.concurrency

Get or set the concurrency limit.

limitFunction(fn, options) named export

Returns a function with limited concurrency.

The returned function manages its own concurrent executions, allowing you to call it multiple times without exceeding the specified concurrency limit.

Ideal for scenarios where you need to control the number of simultaneous executions of a single function, rather than managing concurrency across multiple functions.

import {limitFunction} from 'p-limit';

const limitedFunction = limitFunction(async () => {
	return doSomething();
}, {concurrency: 1});

const input = Array.from({length: 10}, limitedFunction);

// Only one promise is run at once.
await Promise.all(input);

fn

Type: Function

Promise-returning/async function.

options

Type: object

concurrency

Type: number
Minimum: 1

Concurrency limit.

rejectOnClear

Type: boolean
Default: false

Reject pending promises with an AbortError when clearQueue() is called. This is recommended if you await the returned promises, for example with Promise.all, so pending tasks do not remain unresolved after clearQueue().

limitedFunction.clearQueue()

Discard pending calls that have not started yet.

When rejectOnClear is enabled, pending promises are rejected with an AbortError. Otherwise, their promises remain unresolved.

This does not cancel calls that are already running.

Recipes

See recipes.md for common use cases and patterns.

FAQ

How is this different from the p-queue package?

This package is only about limiting the number of concurrent executions, while p-queue is a fully featured queue implementation with lots of different options, introspection, and ability to pause the queue.

Related

  • p-throttle - Throttle promise-returning & async functions
  • p-debounce - Debounce promise-returning & async functions
  • p-map - Run promise-returning & async functions concurrently with different inputs
  • p-all - Run promise-returning & async functions concurrently with optional limited concurrency
  • More…