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 年
GitHub Starsランキング
統計詳細
パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
p-limit180,627,2712,70211.7 kB52ヶ月前MIT
async73,829,58528,218808 kB221年前MIT
bluebird35,363,20920,769-1276年前MIT
promise-limit1,094,323143-107年前ISC
promise-queue962,603230-108年前MIT
機能比較: p-limit vs async vs bluebird vs promise-limit vs promise-queue

並行処理の制御

  • p-limit:

    p-limitは、並行処理の数を簡単に制限するためのライブラリです。指定した数のタスクのみを同時に実行し、残りは待機します。シンプルなAPIで、リソースの使用を効率的に管理できます。

  • async:

    asyncは、並行処理の制御に関して多くの機能を提供しますが、特定の制限を設けることはできません。代わりに、async.parallelLimitasync.eachLimitなどの関数を使用して、並行処理の数を手動で制御できます。

  • bluebird:

    bluebirdは、プロミスの並行処理を制御するためのPromise.mapメソッドを提供します。concurrencyオプションを使用して、同時に実行するプロミスの数を制限できます。これにより、リソースの使用を最適化し、過負荷を防ぐことができます。

  • promise-limit:

    promise-limitは、指定した数のプロミスのみを同時に実行するための軽量なライブラリです。並行処理の制御がシンプルで、リソースの使用を最適化します。特に、同時実行数を制限したい場合に便利です。

  • promise-queue:

    promise-queueは、プロミスをキューに入れて順番に実行します。並行処理の数を制限することもでき、タスクの実行順序を保証します。リソースの競合を避けるために、タスクを順次処理したい場合に適しています。

エラーハンドリング

  • p-limit:

    p-limitは、エラーハンドリングを自動で行いません。タスク内でエラーが発生した場合は、プロミスが拒否されます。タスクのエラー処理は、タスク関数内で行う必要があります。

  • async:

    asyncは、コールバックベースのエラーハンドリングを使用します。各タスクがエラーを返すと、次のタスクは実行されず、エラーがコールバックに渡されます。プロミスを使用する場合は、Promisecatchメソッドを使用してエラーを処理できます。

  • bluebird:

    bluebirdは、プロミスベースのエラーハンドリングを提供します。catchメソッドを使用してエラーを捕捉し、finallyメソッドで後処理を行うことができます。エラーハンドリングが強化されており、複雑な非同期フローでも効果的にエラーを管理できます。

  • promise-limit:

    promise-limitは、エラーハンドリングをタスク内で行う必要があります。タスクがエラーを返すと、プロミスが拒否されますが、ライブラリ自体にはエラーハンドリング機能はありません。

  • promise-queue:

    promise-queueは、プロミスが拒否された場合、キュー内の次のタスクが自動で実行されます。エラー処理はタスク内で行う必要がありますが、キューの実行は継続されます。

APIのシンプルさ

  • p-limit:

    p-limitは、非常にシンプルで直感的なAPIを提供します。並行処理の制限を設定するだけで、すぐに使用できます。

  • async:

    asyncは、豊富な機能を提供しますが、APIはやや複雑です。特に、コールバック、プロミス、ストリームを統合しているため、使いこなすには時間がかかることがあります。

  • bluebird:

    bluebirdは、プロミスに特化したシンプルなAPIを提供します。特に、プロミスのチェイニングやエラーハンドリングが直感的で、使いやすいです。

  • promise-limit:

    promise-limitは、シンプルなAPIで、プロミスの並行処理を簡単に制御できます。ドキュメントもわかりやすく、すぐに実装できます。

  • promise-queue:

    promise-queueは、プロミスをキューに入れて順番に実行するシンプルなAPIを提供します。キューの管理も簡単で、使いやすいです。

パフォーマンス

  • p-limit:

    p-limitは、並行処理の数を制限することで、リソースの使用を最適化します。シンプルな実装でありながら、効率的にリソースを管理できます。

  • async:

    asyncは、非同期処理を効率的に管理しますが、特に並行処理の制限に関しては手動で設定する必要があります。リソースの使用を最適化するためには、開発者が適切に制御する必要があります。

  • bluebird:

    bluebirdは、高性能なプロミスライブラリで、特に並行処理やエラーハンドリングにおいて最適化されています。パフォーマンスが重要なアプリケーションに適しています。

  • promise-limit:

    promise-limitは、プロミスの並行処理を軽量に制御するため、リソースの使用を効率的に管理できます。特に、同時実行数を制限することで、過負荷を防ぎます。

  • promise-queue:

    promise-queueは、プロミスを順番に実行するため、リソースの競合を避けることができます。並行処理の制限も可能で、リソースの使用を最適化します。

Ease of Use: Code Examples

  • p-limit:

    並行処理の制限(p-limit

    const pLimit = require('p-limit');
    
    // 並行処理の制限
    const limit = pLimit(2); // 同時に実行するタスクの数を2に制限
    
    const tasks = [
      () => asyncTask(1000, 'タスク1完了'),
      () => asyncTask(500, 'タスク2完了'),
      () => asyncTask(2000, 'タスク3完了'),
      () => asyncTask(1500, 'タスク4完了'),
    ];
    
    const limitedTasks = tasks.map((task) => limit(task));
    Promise.all(limitedTasks).then((results) => {
      console.log('制限されたタスクの結果:', results);
    });
    
  • async:

    非同期処理の例(async

    const async = require('async');
    
    // 非同期タスクの例
    const task1 = (callback) => {
      setTimeout(() => callback(null, 'タスク1完了'), 1000);
    };
    const task2 = (callback) => {
      setTimeout(() => callback(null, 'タスク2完了'), 500);
    };
    const task3 = (callback) => {
      setTimeout(() => callback(null, 'タスク3完了'), 2000);
    };
    
    // 並行処理の例
    async.parallel([task1, task2, task3], (err, results) => {
      if (err) throw err;
      console.log('すべてのタスクが完了:', results);
    });
    
  • bluebird:

    プロミスの例(bluebird

    const Promise = require('bluebird');
    
    // 非同期タスクの例
    const asyncTask = (time, result) => {
      return new Promise((resolve) => setTimeout(() => resolve(result), time));
    };
    
    // 並行処理の例
    const task1 = asyncTask(1000, 'タスク1完了');
    const task2 = asyncTask(500, 'タスク2完了');
    const task3 = asyncTask(2000, 'タスク3完了');
    
    Promise.all([task1, task2, task3]).then((results) => {
      console.log('すべてのタスクが完了:', results);
    });
    
  • promise-limit:

    プロミスの並行処理制限(promise-limit

    const promiseLimit = require('promise-limit');
    
    // 並行処理の制限
    const limit = promiseLimit(2); // 同時に実行するプロミスの数を2に制限
    
    const tasks = [
      () => asyncTask(1000, 'タスク1完了'),
      () => asyncTask(500, 'タスク2完了'),
      () => asyncTask(2000, 'タスク3完了'),
      () => asyncTask(1500, 'タスク4完了'),
    ];
    
    const limitedTasks = tasks.map((task) => limit(task));
    Promise.all(limitedTasks).then((results) => {
      console.log('制限されたプロミスの結果:', results);
    });
    
  • promise-queue:

    プロミスキューの例(promise-queue

    const PromiseQueue = require('promise-queue');
    
    const queue = new PromiseQueue(2, Infinity); // 同時に実行するプロミスの数を2に制限
    
    const asyncTask = (time, result) => {
      return new Promise((resolve) => setTimeout(() => resolve(result), time));
    };
    
    const tasks = [
      () => asyncTask(1000, 'タスク1完了'),
      () => asyncTask(500, 'タスク2完了'),
      () => asyncTask(2000, 'タスク3完了'),
      () => asyncTask(1500, 'タスク4完了'),
    ];
    
    // タスクをキューに追加
    tasks.forEach((task) => queue.add(task));
    
    queue.onIdle().then(() => {
      console.log('すべてのタスクが完了');
    });
    
選び方: p-limit vs async vs bluebird vs promise-limit vs promise-queue
  • p-limit:

    p-limitを選択するのは、並行処理の数を簡単に制限したい場合です。シンプルで軽量なライブラリで、リソースの使用を最適化し、過負荷を防ぐことができます。特に、APIリクエストやファイル処理など、同時に実行するタスクの数を制御したい場合に役立ちます。

  • async:

    asyncを選択するのは、非同期処理を包括的に管理したい場合です。コールバック、プロミス、ストリームをサポートしており、複雑な非同期フローを簡素化できます。特に、非同期タスクの実行順序や依存関係を管理する必要がある場合に便利です。

  • bluebird:

    bluebirdを選択するのは、高性能なプロミス処理が必要な場合です。プロミスの最適化、エラーハンドリング、並行処理の制御など、豊富な機能を提供します。特に、プロミスのパフォーマンスが重要なアプリケーションに適しています。

  • promise-limit:

    promise-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
Minimum: 1

Concurrency limit.

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.

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))).

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 teardown 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.

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.

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…