UNPKG

6.7 kBMarkdownView Raw
1# es6-promise-pool
2
3[![npm](https://img.shields.io/npm/v/es6-promise-pool.svg)](https://www.npmjs.com/package/es6-promise-pool) ![Bower](https://img.shields.io/bower/v/es6-promise-pool.svg) [![Build Status](https://img.shields.io/travis/timdp/es6-promise-pool.svg)](https://travis-ci.org/timdp/es6-promise-pool) [![Coverage Status](https://img.shields.io/coveralls/timdp/es6-promise-pool.svg)](https://coveralls.io/r/timdp/es6-promise-pool) [![JavaScript Standard Style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](https://github.com/feross/standard)
4
5Runs `Promise`s in a pool that limits their maximum concurrency.
6
7## Motivation
8
9An ECMAScript 6 `Promise` is a great way of handling asynchronous operations.
10The `Promise.all` function provides an easy interface to let a bunch of promises
11settle concurrently.
12
13However, it's an all-or-nothing approach: all your promises get created
14simultaneously. If you have a ton of operations that you want to run with _some_
15concurrency, `Promise.all` is no good.
16
17Instead, you probably want to limit the maximum number of simultaneous
18operations. That's where this module comes in. It provides an easy way of
19waiting for any number of promises to settle, while imposing an upper bound on
20the number of simultaneously executing promises.
21
22The promises can be created in a just-in-time fashion. You essentially pass a
23function that produces a new promise every time it is called. On modern
24platforms, you can also use ES6 generator functions for this.
25
26## Compatibility
27
28This module can be used both under **Node.js** (version 0.10 and up) and on the
29**Web**. If your platform does not have a `Promise` implementation, it will be
30polyfilled by [ES6-Promise](https://github.com/jakearchibald/es6-promise).
31
32## Installation
33
34```bash
35npm install --save es6-promise-pool
36```
37
38```bash
39bower install --save es6-promise-pool
40```
41
42```html
43<script src="es6-promise.js"></script>
44<script>ES6Promise.polyfill()</script>
45<script src="es6-promise-pool.js"></script>
46```
47
48## Usage
49
50```js
51// On the Web, leave out these two lines and use the script tags above instead.
52var Promise = require('es6-promise').Promise
53var promisePool = require('es6-promise-pool')
54
55var PromisePool = promisePool.PromisePool
56
57var promiseProducer = function () {
58 // Your code goes here.
59 // If there is work left to be done, return the next work item as a promise.
60 // Otherwise, return null to indicate that all promises have been created.
61 // Scroll down for an example.
62}
63
64// The number of promises to process simultaneously.
65var concurrency = 3
66
67// Create a pool.
68var pool = new PromisePool(promiseProducer, concurrency)
69
70// Start the pool.
71var poolPromise = pool.start()
72
73// Wait for the pool to settle.
74poolPromise.then(function () {
75 console.log('All promises fulfilled')
76}, function (error) {
77 console.log('Some promise rejected: ' + error.message)
78})
79```
80
81## Producers
82
83The `PromisePool` constructor takes a `Promise`-producing function as its first
84argument. Let's first assume that we have this helper function that returns a
85promise for the given `value` after `time` milliseconds:
86
87```js
88var delayValue = function (value, time) {
89 return new Promise(function (resolve, reject) {
90 console.log('Resolving ' + value + ' in ' + time + ' ms')
91 setTimeout(function () {
92 console.log('Resolving: ' + value)
93 resolve(value)
94 }, time)
95 })
96}
97```
98
99### Function
100
101Now, let's use the helper function above to create five such promises, which
102are each fulfilled after a second. Because of the `concurrency` of `3`, the
103first three promises will be fulfilled after one second. Then, the remaining two
104will be processed and fulfilled after another second.
105
106```js
107var count = 0
108var promiseProducer = function () {
109 if (count < 5) {
110 count++
111 return delayValue(count, 1000)
112 } else {
113 return null
114 }
115}
116
117var pool = new PromisePool(promiseProducer, 3)
118
119pool.start()
120 .then(function () {
121 console.log('Complete')
122 })
123```
124
125### Generator
126
127We can achieve the same result with ECMAScript 6 generator functions.
128
129```js
130var promiseProducer = function* () {
131 for (var count = 1; count <= 5; count++) {
132 yield delayValue(count, 1000)
133 }
134};
135
136var pool = new PromisePool(promiseProducer, 3)
137
138pool.start()
139.then(function () {
140 console.log('Complete')
141})
142```
143
144## Events
145
146We can also ask the promise pool to notify us when an individual promise is
147fulfilled or rejected. The pool fires `fulfilled` and `rejected` events exactly
148for this purpose.
149
150```js
151var pool = new PromisePool(promiseProducer, concurrency)
152
153pool.addEventListener('fulfilled', function (event) {
154 // The event contains:
155 // - target: the PromisePool itself
156 // - data:
157 // - promise: the Promise that got fulfilled
158 // - result: the result of that Promise.
159 console.log('Fulfilled: ' + event.data.result)
160})
161
162pool.addEventListener('rejected', function (event) {
163 // The event contains:
164 // - target: the PromisePool itself
165 // - data:
166 // - promise: the Promise that got rejected
167 // - error: the Error for the rejection.
168 console.log('Rejected: ' + event.data.error.message)
169})
170
171pool.start()
172 .then(function () {
173 console.log('Complete')
174 })
175```
176
177## Alternatives
178
179- [Async.js](https://github.com/caolan/async)
180- [Promise Pool](https://github.com/vilic/promise-pool)
181- [qlimit](https://www.npmjs.com/package/qlimit)
182
183## Author
184
185[Tim De Pauw](https://tmdpw.eu/)
186
187## License
188
189Copyright &copy; 2015 Tim De Pauw
190
191Permission is hereby granted, free of charge, to any person obtaining a copy
192of this software and associated documentation files (the "Software"), to deal
193in the Software without restriction, including without limitation the rights
194to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
195copies of the Software, and to permit persons to whom the Software is
196furnished to do so, subject to the following conditions:
197
198The above copyright notice and this permission notice shall be included in all
199copies or substantial portions of the Software.
200
201THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
202IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
203FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
204AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
205LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
206OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
207SOFTWARE.