Compare commits

..

8 Commits

Author SHA1 Message Date
178672ad0d v1.0.3: use index as well 2019-11-25 16:05:46 -07:00
9beae76631 make Prettier 2019-11-25 15:43:58 -07:00
dd206891d5 make Prettier 2019-11-25 15:38:55 -07:00
038b6cac33 syntax fix 2019-06-14 10:52:27 -06:00
b193312ed6 bump v1.0.2 2019-06-13 17:52:05 -06:00
81333f4c47 update README 2019-06-13 17:51:53 -06:00
0c2692f9fb bump v1.0.1 2019-06-13 17:47:44 -06:00
42602e34c8 update README 2019-06-13 17:47:27 -06:00
5 changed files with 190 additions and 176 deletions

View File

@ -1,14 +1,19 @@
# [batchasync.js](https://git.coolaj86.com/coolaj86/batchasync.js) # [batchasync.js](https://git.coolaj86.com/coolaj86/batchasync.js)
Like forEachAsync, or Promise.all(), but handling a bounded number of items at any given time. Like calling `map()` and resolving with `Promise.all()`,
but handling a bounded number of items at any given time.
## Install Want to read about it?
- [Batching async requests in < 50 lines of VanillaJS](https://coolaj86.com/articles/batching-async-requests-50-lines-of-vanilla-js/)
# Install
```bash ```bash
npm install --save batchasync npm install --save batchasync
``` ```
## Usage # Usage
```js ```js
// Browsers // Browsers
@ -34,10 +39,14 @@ batchAsync(batchSize, things, doStuff).then(function(results) {
}); });
``` ```
### Returning 'undefined' ## A note on `undefined`
Returning `undefined` will cause an exception to be thrown Returning `undefined` will cause an exception to be thrown,
(because it looks like a skipped promise). Return `null` instead. and the Promise to be rejected.
This is on purpose - because `undefined` is indistinguishable from a skipped Promise.
Return `null` instead.
**Example (bad)**: **Example (bad)**:

View File

@ -1,5 +1,5 @@
(function(exports) { (function(exports) {
'use strict'; "use strict";
exports.batchAsync = function(limit, arr, doStuff) { exports.batchAsync = function(limit, arr, doStuff) {
arr = arr.slice(0); arr = arr.slice(0);
@ -37,7 +37,7 @@ exports.batchAsync = function (limit, arr, doStuff) {
var p; var p;
try { try {
p = doStuff(task); p = doStuff(task, index, arr);
} catch (e) { } catch (e) {
// we need to handle, and bubble, synchronous errors // we need to handle, and bubble, synchronous errors
error = e; error = e;
@ -48,7 +48,7 @@ exports.batchAsync = function (limit, arr, doStuff) {
// add support for sync by rapping in a promise // add support for sync by rapping in a promise
Promise.resolve(p) Promise.resolve(p)
.then(function(result) { .then(function(result) {
if ('undefined' === typeof result) { if ("undefined" === typeof result) {
throw new Error( throw new Error(
"result was 'undefined'. Please return 'null' to signal that you didn't just forget to return another promise." "result was 'undefined'. Please return 'null' to signal that you didn't just forget to return another promise."
); );
@ -67,5 +67,4 @@ exports.batchAsync = function (limit, arr, doStuff) {
doMoreStuff(); doMoreStuff();
}); });
}; };
})("undefined" !== typeof window ? window : module.exports);
}('undefined' !== typeof window ? window : module.exports));

5
package-lock.json generated Normal file
View File

@ -0,0 +1,5 @@
{
"name": "batchasync",
"version": "1.0.3",
"lockfileVersion": 1
}

View File

@ -1,6 +1,6 @@
{ {
"name": "batchasync", "name": "batchasync",
"version": "1.0.0", "version": "1.0.3",
"description": "Like forEachAsync, or Promise.all(), but handling a bounded number of items at any given time.", "description": "Like forEachAsync, or Promise.all(), but handling a bounded number of items at any given time.",
"main": "batchasync.js", "main": "batchasync.js",
"scripts": { "scripts": {

53
test.js
View File

@ -1,15 +1,17 @@
(function(exports) { (function(exports) {
'use strict'; "use strict";
var batchAsync = exports.batchAsync || require('./batchasync.js').batchAsync; var batchAsync =
exports.batchAsync || require("./batchasync.js").batchAsync;
function testBatch() { function testBatch() {
var timeouts = [100, 80, 20, 500, 50, 30, 200, 300]; var timeouts = [100, 80, 20, 500, 50, 30, 200, 300];
console.info(timeouts);
var tasks = timeouts.map(function(timeout, i) { var tasks = timeouts.map(function(timeout, i) {
return function() { return function() {
return promiseTimeout(timeout).then(function() { return promiseTimeout(timeout).then(function() {
console.log('task:', i, timeouts[i]); //console.log("task:", i, timeouts[i]);
return i; return i + ":" + timeouts[i];
}); });
}; };
}); });
@ -19,40 +21,40 @@ function testBatch() {
return task(); return task();
}) })
.then(function(results) { .then(function(results) {
console.info('results:', results); console.info("results:", results);
if (len !== results.length) { if (len !== results.length) {
throw new Error('result set too small'); throw new Error("result set too small");
} }
if (results.join(' ') !== results.sort().join(' ')) { if (results.join(" ") !== results.sort().join(" ")) {
throw new Error('result set out-of-order'); throw new Error("result set out-of-order");
} }
}) })
.then(function() { .then(function() {
return batchAsync(4, [], 'not a function').then(function() { return batchAsync(4, [], "not a function").then(function() {
console.info('Handled ZERO tasks correctly.'); console.info("Handled ZERO tasks correctly.");
}); });
}) })
.then(function() { .then(function() {
return batchAsync(4, timeouts, function(x) { return batchAsync(4, timeouts, function(x) {
return x; return x;
}).then(function(results) { }).then(function(results) {
if (results.join(' ') !== timeouts.join(' ')) { if (results.join(" ") !== timeouts.join(" ")) {
console.error(results); console.error(results);
throw new Error('sync result set out-of-order'); throw new Error("sync result set out-of-order");
} }
console.info('Handled sync tasks correctly.'); console.info("Handled sync tasks correctly.");
}); });
}) })
.then(function() { .then(function() {
return batchAsync(4, tasks, function(task) { return batchAsync(4, tasks, function(task) {
if (0 === Math.floor(Math.random() * 2) % 2) { if (0 === Math.floor(Math.random() * 2) % 2) {
throw new Error('any async error will do'); throw new Error("any async error will do");
} }
return task(); return task();
}) })
.then(function(results) { .then(function(results) {
console.log(results); console.log(results);
var e = new Error('async rejection should not pass!'); var e = new Error("async rejection should not pass!");
e.FAIL = true; e.FAIL = true;
throw e; throw e;
}) })
@ -60,18 +62,18 @@ function testBatch() {
if (e.FAIL) { if (e.FAIL) {
throw e; throw e;
} }
console.info('Pass: Exception thrown when expected'); console.info("Pass: Exception thrown when expected");
}); });
}) })
.then(function() { .then(function() {
return batchAsync(4, timeouts, function() { return batchAsync(4, timeouts, function() {
if (0 === Math.floor(Math.random() * 2) % 2) { if (0 === Math.floor(Math.random() * 2) % 2) {
throw new Error('any sync error will do'); throw new Error("any sync error will do");
} }
return null; return null;
}) })
.then(function(results) { .then(function(/*results*/) {
var e = new Error('should not pass sync exception!'); var e = new Error("should not pass sync exception!");
e.FAIL = true; e.FAIL = true;
throw e; throw e;
}) })
@ -82,29 +84,28 @@ function testBatch() {
}) })
.then(function() { .then(function() {
// wait for the tasks the error left dangling to print their message // wait for the tasks the error left dangling to print their message
console.info('Pass: Promise rejected when expected'); console.info("Pass: Promise rejected when expected");
return promiseTimeout(1000); return promiseTimeout(1000);
}); });
}); });
} }
function promiseTimeout(timeout) { function promiseTimeout(timeout) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve) {
setTimeout(resolve, timeout); setTimeout(resolve, timeout);
}); });
} }
testBatch() testBatch()
.then(function() { .then(function() {
console.info('PROBABLY PASSED'); console.info("PROBABLY PASSED");
console.info( console.info(
'We tested what could be tested without knowing Passed what could be tested Do the results make sense?' "We tested what could be tested. Do the results make sense?"
); );
}) })
.catch(function(e) { .catch(function(e) {
console.error('FAIL!'); console.error("FAIL!");
console.error(e); console.error(e);
process.exit(500); process.exit(500);
}); });
})("undefined" !== typeof window ? window : module.exports);
}('undefined' !== typeof window ? window : module.exports));