Skip to content

Commit

Permalink
Initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
zewish committed Oct 8, 2016
0 parents commit 96e648e
Show file tree
Hide file tree
Showing 8 changed files with 263 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
language: node_js
node_js:
- "lts"
branches:
only:
- "master"
before_script:
- npm install
script: npm test
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
[![NPM version](https://img.shields.io/npm/v/prottle.svg?style=flat-square)](https://www.npmjs.com/package/prottle)
[![Build Status](https://travis-ci.org/zewish/prottle.svg?branch=master)](https://travis-ci.org/zewish/prottle)
[![Downloads](https://img.shields.io/npm/dm/prottle.svg?style=flat-square)](https://www.npmjs.com/package/prottle)

Promise.all() throttle - Prottle

- Executes promise-returning functions in batches;
- Once batch 1 is finished it's time for the next one;
- Backend - Node 4.0+ supported;
- Frontend - works with ES2015 preset using babelify. Use a Promise polyfill for IE.

Installation
------------
```bash
$ npm install prottle --save
```

Example - resolved
------------------
```js
'use strict';
let prottle = require('prottle');

prottle(2, [
// batch 1
() => Promise.resolve(1)
, () => Promise.resolve(2)
// batch 2
, () => Promise.resolve(3)
, () => new Promise((resolve, reject) => {
setTimeout(() => resolve(4), 3000);
})
// batch 3
, () => Promise.resolve(5)
])
.then(res => {
console.log(res); // [ 1, 2, 3, 4, 5 ]
});
```

Example - rejected
------------------
```js
'use strict';
let prottle = require('prottle');

prottle(2, [
() => Promise.resolve('yay')
, () => Promise.reject('beep boop')
, () => Promise.resolve('wow')
])
.catch(err => {
console.log(err); // beep boop
});
```

Works with returned values too!
-------------------------------
```js
'use strict';
let prottle = require('prottle');

prottle(2, [
() => 1
, () => 2
, () => 3
])
.then(res => {
console.log(res); // [ 1, 2, 3 ]
});
```
32 changes: 32 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "prottle",
"version": "1.0.0",
"description": "Promise.all() throttle",
"main": "src/index.js",
"scripts": {
"test": "mocha ./test/*.test.js"
},
"author": "Iskren Slavov <iskren.s@gmail.com>",
"license": "BSD-2-Clause",
"devDependencies": {
"chai": "^3.5.0",
"chai-as-promised": "^6.0.0",
"mocha": "^3.1.0"
},
"keywords": [
"promise",
"throttle",
"limit",
"promise.all",
"promises",
"browserify"
],
"repository": {
"type": "git",
"url": "https://github.com/zewish/prottle.git"
},
"bugs": {
"url": "https://github.com/zewish/prottle/issues"
},
"homepage": "https://github.com/zewish/prottle"
}
48 changes: 48 additions & 0 deletions src/execute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use strict';

let EventEmitter = require('events');

module.exports = (limit, promises) => {
let results = []
, emitter = new EventEmitter();

let run = (batch, id) => {
Promise.all(batch.map(
fn => Promise.resolve(fn())
))
.then(res => {
results.push.apply(results, res);
emitter.emit(`end:${id}`);
})
.catch(err => {
emitter.emit('error', err);
});
};

let add = (batch, id) => {
if (id === 0) {
return run(batch, id);
}

emitter.once(`end:${id-1}`, () => run(batch, id));
};

let idx = -1;
while (promises.length) {
add(
promises.splice(0, limit)
, ++idx
);
}

return new Promise((resolve, reject) => {
emitter
.once(`end:${idx}`, () => {
resolve(results);
})
.once('error', err => {
emitter.removeAllListeners();
reject(err);
});
});
};
17 changes: 17 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

let execute = require('./execute.js');

module.exports = (limit, promises) => {
limit = parseInt(limit);

if (isNaN(limit) || limit <= 0) {
return Promise.reject(Error('Limit must be at least 1'));
}

if (!Array.isArray(promises)) {
return Promise.reject(Error('Array of promises required'));
}

return execute(limit, promises);
};
39 changes: 39 additions & 0 deletions test/execute.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict';

require('chai')
.use(require('chai-as-promised'))
.should();

describe('execute.js', () => {
let execute;

beforeEach(() => {
execute = require('../src/execute.js');
});

it('exports a fn', () => {
execute.should.be.a('function');
});

it('resolves', () => {
return execute(3, [
() => Promise.resolve(1)
, () => Promise.resolve(2)
, () => Promise.resolve(3)
, () => Promise.resolve(4)
, () => Promise.resolve(5)
])
.should.eventually.eql([ 1, 2, 3, 4, 5 ]);
});

it('rejects', () => {
return execute(2, [
() => Promise.resolve(1)
, () => Promise.resolve(2)
, () => Promise.resolve(3)
, () => Promise.reject('beep boop')
, () => Promise.resolve(5)
])
.should.be.rejectedWith('beep boop');
});
});
46 changes: 46 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict';

require('chai')
.use(require('chai-as-promised'))
.should();

describe('index.js', () => {
let index = require('../src/index.js');

it('rejects with limit error', () => {
return index()
.catch((err) => {
err.message.should.equal('Limit must be at least 1');
});
});

it('rejects with limit error', () => {
return index(0)
.catch((err) => {
err.message.should.equal('Limit must be at least 1');
});
});

it('rejects with limit error', () => {
return index('dsad')
.catch((err) => {
err.message.should.equal('Limit must be at least 1');
});
});

it('rejects with array error', () => {
return index(1, 'boo')
.catch((err) => {
err.message.should.equal('Array of promises required');
});
});

it('resolves', () => {
return index(1, [
() => Promise.resolve(1)
, () => Promise.resolve(2)
, () => Promise.resolve(3)
])
.should.eventually.eql([ 1, 2, 3 ]);
});
});

0 comments on commit 96e648e

Please sign in to comment.