asynckit
Advanced tools
Comparing version 0.1.0 to 0.2.0
{ | ||
"name": "asynckit", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "Minimal async jobs utility library", | ||
@@ -10,6 +10,7 @@ "main": "index.js", | ||
"test": "istanbul cover --reporter=json tape -- 'test/test-*.js' | tap-spec", | ||
"win-test": "tape test/test-*.js", | ||
"browser": "browserify -t browserify-istanbul test/test-*.js | obake --coverage | tap-spec", | ||
"report": "istanbul report", | ||
"size": "browserify index.js | size-table asynckit", | ||
"debug": "tape test/*.js | tap-spec" | ||
"debug": "tape test/test-*.js | tap-spec" | ||
}, | ||
@@ -57,3 +58,4 @@ "pre-commit": [ | ||
"tape": "^4.5.1" | ||
} | ||
}, | ||
"dependencies": {} | ||
} |
@@ -7,3 +7,3 @@ // Public API | ||
* | ||
* @param {array|object} list - array or object to iterate over | ||
* @param {array|object} list - array or object (named list) to iterate over | ||
* @param {function} iterator - iterator to run | ||
@@ -15,3 +15,3 @@ * @param {object} [state] - current job status | ||
{ | ||
var index; | ||
var key, isNamedList = !Array.isArray(list); | ||
@@ -26,13 +26,18 @@ if (typeof state == 'function') | ||
{ | ||
state = {index: 0, jobs: [], results: []}; | ||
state = { | ||
index : 0, | ||
namedList: isNamedList ? Object.keys(list) : null, | ||
jobs : {}, | ||
results : isNamedList ? {} : [] | ||
}; | ||
} | ||
// store current index | ||
index = state.index; | ||
key = isNamedList ? state['namedList'][state.index] : state.index; | ||
state.jobs[index] = iterator(list[index], function(error, output) | ||
state.jobs[key] = runJob(iterator, key, list[key], function(error, output) | ||
{ | ||
// don't repeat yourself | ||
// skip secondary callbacks | ||
if (!(index in state.jobs)) | ||
if (!(key in state.jobs)) | ||
{ | ||
@@ -43,3 +48,3 @@ return; | ||
// clean up jobs | ||
delete state.jobs[index]; | ||
delete state.jobs[key]; | ||
@@ -50,5 +55,4 @@ if (error) | ||
// stop still active jobs | ||
state.jobs.map(invoke); | ||
// and reset the list | ||
state.jobs = {}; | ||
abortJobs(state); | ||
// return salvaged results | ||
@@ -59,3 +63,3 @@ callback(error, state.results); | ||
state.results[index] = output; | ||
state.results[key] = output; | ||
@@ -74,3 +78,3 @@ // looks like it's the last one | ||
// proceed to the next element | ||
if (state.index < list.length) | ||
if (state.index < (state['namedList'] || list).length) | ||
{ | ||
@@ -82,12 +86,53 @@ parallel(list, iterator, state, callback); | ||
/** | ||
* Invokes provided function | ||
* Runs iterator over provided job element | ||
* | ||
* @param {function} func - function to invoke | ||
* @param {function} iterator - iterator to invoke | ||
* @param {string|number} key - key/index of the element in the list of jobs | ||
* @param {mixed} item - job description | ||
* @param {function} callback - invoked after iterator is done with the job | ||
* @returns {function|mixed} - job abort function or something else | ||
*/ | ||
function invoke(func) | ||
function runJob(iterator, key, item, callback) | ||
{ | ||
if (typeof func == 'function') | ||
var abort; | ||
// allow shortcut if iterator expects only two arguments | ||
if (iterator.length == 2) | ||
{ | ||
func(); | ||
abort = iterator(item, callback); | ||
} | ||
// otherwise go with full three arguments | ||
else | ||
{ | ||
abort = iterator(item, key, callback); | ||
} | ||
return abort; | ||
} | ||
/** | ||
* Aborts leftover active jobs | ||
* | ||
* @param {object} state - current state object | ||
*/ | ||
function abortJobs(state) | ||
{ | ||
Object.keys(state.jobs).forEach(clean.bind(state)); | ||
// reset leftover jobs | ||
state.jobs = {}; | ||
} | ||
/** | ||
* Cleans up leftover job by invoking abort function for the provided job id | ||
* | ||
* @this state | ||
* @param {string|number} key - job id to abort | ||
*/ | ||
function clean(key) | ||
{ | ||
if (typeof this.jobs[key] == 'function') | ||
{ | ||
this.jobs[key](); | ||
} | ||
} |
@@ -17,5 +17,5 @@ # asynckit [![NPM Module](https://img.shields.io/npm/v/asynckit.svg?style=flat)](https://www.npmjs.com/package/asynckit) | ||
| :----------------- | ------: | | ||
| asynckit.js | 2.27 kB | | ||
| asynckit.min.js | 958 B | | ||
| asynckit.min.js.gz | 491 B | | ||
| asynckit.js | 3.47 kB | | ||
| asynckit.min.js | 1.19 kB | | ||
| asynckit.min.js.gz | 590 B | | ||
@@ -75,2 +75,44 @@ | ||
Also it supports named jobs, listed via object. | ||
```javascript | ||
var parallel = require('asynckit/parallel') | ||
, assert = require('assert') | ||
; | ||
var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 } | ||
, expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 } | ||
, expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ] | ||
, expectedKeys = [ 'first', 'one', 'two', 'four', 'eight', 'sixteen', 'thirtyTwo', 'sixtyFour' ] | ||
, target = [] | ||
, keys = [] | ||
; | ||
parallel(source, asyncJob, function(err, result) | ||
{ | ||
assert.deepEqual(result, expectedResult); | ||
assert.deepEqual(target, expectedTarget); | ||
assert.deepEqual(keys, expectedKeys); | ||
}); | ||
// supports full value, key, callback (shortcut) interface | ||
function asyncJob(item, key, cb) | ||
{ | ||
// different delays (in ms) per item | ||
var delay = item * 25; | ||
// pretend different jobs take different time to finish | ||
// and not in consequential order | ||
var timeoutId = setTimeout(function() { | ||
keys.push(key); | ||
target.push(item); | ||
cb(null, item * 2); | ||
}, delay); | ||
// allow to cancel "leftover" jobs upon error | ||
// return function, invoking of which will abort this job | ||
return clearTimeout.bind(null, timeoutId); | ||
} | ||
``` | ||
## Want to Know More? | ||
@@ -77,0 +119,0 @@ |
9759
117
125