Comparing version 3.0.1-0 to 3.0.1
@@ -6,3 +6,3 @@ import auto from './auto'; | ||
var FN_ARGS = /^(?:async\s+)?(?:function)?\s*[^(]*\(\s*([^)]+)\s*\)(?:\s*{)/m; | ||
var ARROW_FN_ARGS = /^(?:async\s+)?\(?\s*([^)^=]+)\s*\)?(?:\s*=>)/m; | ||
var ARROW_FN_ARGS = /^(?:async\s+)?(?:function\s+)?\(?\s*([^)^=]+)\s*\)?(?:\s*=>)/m; | ||
var FN_ARG_SPLIT = /,/; | ||
@@ -9,0 +9,0 @@ var FN_ARG = /(=.+)?(\s*)$/; |
37
cargo.js
import queue from './internal/queue'; | ||
/** | ||
* A cargo of tasks for the worker function to complete. Cargo inherits all of | ||
* the same methods and event callbacks as [`queue`]{@link module:ControlFlow.queue}. | ||
* @typedef {Object} CargoObject | ||
* @memberOf module:ControlFlow | ||
* @property {Function} length - A function returning the number of items | ||
* waiting to be processed. Invoke like `cargo.length()`. | ||
* @property {number} payload - An `integer` for determining how many tasks | ||
* should be process per round. This property can be changed after a `cargo` is | ||
* created to alter the payload on-the-fly. | ||
* @property {Function} push - Adds `task` to the `queue`. The callback is | ||
* called once the `worker` has finished processing the task. Instead of a | ||
* single task, an array of `tasks` can be submitted. The respective callback is | ||
* used for every task in the list. Invoke like `cargo.push(task, [callback])`. | ||
* @property {Function} saturated - A callback that is called when the | ||
* `queue.length()` hits the concurrency and further tasks will be queued. | ||
* @property {Function} empty - A callback that is called when the last item | ||
* from the `queue` is given to a `worker`. | ||
* @property {Function} drain - A callback that is called when the last item | ||
* from the `queue` has returned from the `worker`. | ||
* @property {Function} idle - a function returning false if there are items | ||
* waiting or being processed, or true if not. Invoke like `cargo.idle()`. | ||
* @property {Function} pause - a function that pauses the processing of tasks | ||
* until `resume()` is called. Invoke like `cargo.pause()`. | ||
* @property {Function} resume - a function that resumes the processing of | ||
* queued tasks when the queue is paused. Invoke like `cargo.resume()`. | ||
* @property {Function} kill - a function that removes the `drain` callback and | ||
* empties remaining tasks from the queue forcing it to go idle. Invoke like `cargo.kill()`. | ||
*/ | ||
/** | ||
* Creates a `cargo` object with the specified payload. Tasks added to the | ||
@@ -56,3 +26,3 @@ * cargo will be processed altogether (up to the `payload` limit). If the | ||
* unlimited. | ||
* @returns {module:ControlFlow.CargoObject} A cargo object to manage the tasks. Callbacks can | ||
* @returns {module:ControlFlow.QueueObject} A cargo object to manage the tasks. Callbacks can | ||
* attached as certain properties to listen for specific events during the | ||
@@ -77,5 +47,4 @@ * lifecycle of the cargo and inner queue. | ||
* }); | ||
* cargo.push({name: 'baz'}, function(err) { | ||
* console.log('finished processing baz'); | ||
* }); | ||
* await cargo.push({name: 'baz'}); | ||
* console.log('finished processing baz'); | ||
*/ | ||
@@ -82,0 +51,0 @@ export default function cargo(worker, payload) { |
@@ -0,1 +1,8 @@ | ||
# v3.0.1 | ||
## Bug fixes | ||
- Fixed a regression where arrays passed to `queue` and `cargo` would be completely flattened. (#1645) | ||
- Clarified Async's browser support (#1643) | ||
# v3.0.0 | ||
@@ -17,2 +24,3 @@ | ||
- We are now making heavy use of ES2015 features, this means we have dropped out-of-the-box support for Node 4 and earlier, and many old versions of browsers. (#1541, #1553) | ||
- In `queue`, `priorityQueue`, `cargo` and `cargoQueue`, the "event"-style methods, like `q.drain` and `q.saturated` are now methods that register a callback, rather than properties you assign a callback to. They are now of the form `q.drain(callback)`. If you do not pass a callback a Promise will be returned for the next occurrence of the event, making them `await`-able, e.g. `await q.drain()`. (#1586, #1641) | ||
- Calling `callback(false)` will cancel an async method, preventing further iteration and callback calls. This is useful for preventing memory leaks when you break out of an async flow by calling an outer callback. (#1064, #1542) | ||
@@ -22,2 +30,3 @@ - `during` and `doDuring` have been removed, and instead `whilst`, `doWhilst`, `until` and `doUntil` now have asynchronous `test` functions. (#850, #1557) | ||
- `memoize` no longer memoizes errors (#1465, #1466) | ||
- `applyEach`/`applyEachSeries` have a simpler interface, to make them more easily type-able. It always returns a function that takes in a single callback argument. If that callback is omitted, a promise is returned, making it awaitable. (#1228, #1640) | ||
@@ -28,2 +37,3 @@ ## New Features | ||
- Queue objects returned from `queue` now have a `Symbol.iterator` method, meaning they can be iterated over to inspect the current list of items in the queue. (#1459, #1556) | ||
- A ESM-flavored `async.mjs` is included in the `async` package. This is described in the `package.json` `"module"` field, meaning it should be automatically used by Webpack and other compatible bundlers. | ||
@@ -30,0 +40,0 @@ ## Bug fixes |
@@ -15,2 +15,3 @@ import concatLimit from './concatLimit'; | ||
* @category Collection | ||
* @alias flatMap | ||
* @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. | ||
@@ -17,0 +18,0 @@ * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`, |
@@ -14,2 +14,3 @@ import wrapAsync from './internal/wrapAsync'; | ||
* @category Collection | ||
* @alias flatMapLimit | ||
* @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. | ||
@@ -30,3 +31,3 @@ * @param {number} limit - The maximum number of async operations at a time. | ||
if (err) return iterCb(err); | ||
return iterCb(null, args); | ||
return iterCb(err, args); | ||
}); | ||
@@ -33,0 +34,0 @@ }, (err, mapResults) => { |
@@ -13,2 +13,3 @@ import concatLimit from './concatLimit'; | ||
* @category Collection | ||
* @alias flatMapSeries | ||
* @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. | ||
@@ -15,0 +16,0 @@ * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`. |
@@ -43,3 +43,3 @@ import onlyOnce from './internal/onlyOnce'; | ||
var _test = wrapAsync(test); | ||
var results | ||
var results = []; | ||
@@ -46,0 +46,0 @@ function next(err, ...rest) { |
@@ -7,2 +7,5 @@ import eachLimit from './eachLimit'; | ||
* | ||
* Note, that unlike [`each`]{@link module:Collections.each}, this function applies iteratee to each item | ||
* in series and therefore the iteratee functions will complete in order. | ||
* @name eachSeries | ||
@@ -9,0 +12,0 @@ * @static |
@@ -7,2 +7,5 @@ import eachLimit from './eachLimit'; | ||
* | ||
* Note, that unlike [`each`]{@link module:Collections.each}, this function applies iteratee to each item | ||
* in series and therefore the iteratee functions will complete in order. | ||
* @name eachSeries | ||
@@ -9,0 +12,0 @@ * @static |
@@ -30,3 +30,3 @@ import mapLimit from './mapLimit'; | ||
if (err) return iterCb(err); | ||
return iterCb(null, {key, val}); | ||
return iterCb(err, {key, val}); | ||
}); | ||
@@ -33,0 +33,0 @@ }, (err, mapResults) => { |
@@ -231,2 +231,5 @@ /** | ||
findSeries: detectSeries, | ||
flatMap: concat, | ||
flatMapLimit: concatLimit, | ||
flatMapSeries: concatSeries, | ||
forEach: each, | ||
@@ -337,2 +340,5 @@ forEachSeries: eachSeries, | ||
detectSeries as findSeries, | ||
concat as flatMap, | ||
concatLimit as flatMapLimit, | ||
concatSeries as flatMapSeries, | ||
each as forEach, | ||
@@ -339,0 +345,0 @@ eachSeries as forEachSeries, |
@@ -1,17 +0,14 @@ | ||
import initialParams from './initialParams'; | ||
import wrapAsync from './wrapAsync'; | ||
import awaitify from './awaitify' | ||
export default function applyEach(eachfn) { | ||
return function(fns, ...callArgs) { | ||
var go = initialParams(function(args, callback) { | ||
export default function (eachfn) { | ||
return function applyEach(fns, ...callArgs) { | ||
const go = awaitify(function (callback) { | ||
var that = this; | ||
return eachfn(fns, (fn, cb) => { | ||
wrapAsync(fn).apply(that, args.concat(cb)); | ||
wrapAsync(fn).apply(that, callArgs.concat(cb)); | ||
}, callback); | ||
}); | ||
if (callArgs.length) { | ||
return go.apply(this, callArgs); | ||
} | ||
return go; | ||
}; | ||
} |
@@ -11,3 +11,3 @@ import breakLoop from './breakLoop'; | ||
iteratee(value, (err, result) => { | ||
if (err) return callback(err) | ||
if (err || err === false) return callback(err); | ||
@@ -14,0 +14,0 @@ if (check(result) && !testResult) { |
@@ -30,3 +30,3 @@ import isArrayLike from './isArrayLike'; | ||
} | ||
iterCb(); | ||
iterCb(err); | ||
}); | ||
@@ -33,0 +33,0 @@ }, err => { |
@@ -6,4 +6,2 @@ import onlyOnce from './onlyOnce'; | ||
const noop = () => {} | ||
export default function queue(worker, concurrency, payload) { | ||
@@ -20,3 +18,32 @@ if (concurrency == null) { | ||
var workersList = []; | ||
const events = { | ||
error: [], | ||
drain: [], | ||
saturated: [], | ||
unsaturated: [], | ||
empty: [] | ||
} | ||
function on (event, handler) { | ||
events[event].push(handler) | ||
} | ||
function once (event, handler) { | ||
const handleAndRemove = (...args) => { | ||
off(event, handleAndRemove) | ||
handler(...args) | ||
} | ||
events[event].push(handleAndRemove) | ||
} | ||
function off (event, handler) { | ||
if (!event) return Object.keys(events).forEach(ev => events[ev] = []) | ||
if (!handler) return events[event] = [] | ||
events[event] = events[event].filter(ev => ev !== handler) | ||
} | ||
function trigger (event, ...args) { | ||
events[event].forEach(handler => handler(...args)) | ||
} | ||
var processingScheduled = false; | ||
@@ -28,21 +55,24 @@ function _insert(data, insertAtFront, callback) { | ||
q.started = true; | ||
if (!Array.isArray(data)) { | ||
data = [data]; | ||
} | ||
if (data.length === 0 && q.idle()) { | ||
// call drain immediately if there are no tasks | ||
return setImmediate(() => q.drain()); | ||
} | ||
/*if (Array.isArray(data)) { | ||
for (var i = 0, l = data.length; i < l; i++) { | ||
var item = { | ||
data: data[i], | ||
callback: callback || noop | ||
}; | ||
return data.map(datum => _insert(datum, insertAtFront, callback)); | ||
}*/ | ||
if (insertAtFront) { | ||
q._tasks.unshift(item); | ||
} else { | ||
q._tasks.push(item); | ||
var res; | ||
var item = { | ||
data, | ||
callback: callback || function (err, ...args) { | ||
// we don't care about the error, let the global error handler | ||
// deal with it | ||
if (err) return | ||
if (args.length <= 1) return res(args[0]) | ||
res(args) | ||
} | ||
}; | ||
if (insertAtFront) { | ||
q._tasks.unshift(item); | ||
} else { | ||
q._tasks.push(item); | ||
} | ||
@@ -57,5 +87,11 @@ | ||
} | ||
if (!callback) { | ||
return new Promise((resolve) => { | ||
res = resolve | ||
}) | ||
} | ||
} | ||
function _next(tasks) { | ||
function _createCB(tasks) { | ||
return function (err, ...args) { | ||
@@ -77,3 +113,3 @@ numRunning -= 1; | ||
if (err != null) { | ||
q.error(err, task.data); | ||
trigger('error', err, task.data); | ||
} | ||
@@ -83,7 +119,7 @@ } | ||
if (numRunning <= (q.concurrency - q.buffer) ) { | ||
q.unsaturated(); | ||
trigger('unsaturated') | ||
} | ||
if (q.idle()) { | ||
q.drain(); | ||
trigger('drain') | ||
} | ||
@@ -94,2 +130,16 @@ q.process(); | ||
const eventMethod = (name) => (handler) => { | ||
if (!handler) { | ||
return new Promise((resolve, reject) => { | ||
once(name, (err, data) => { | ||
if (err) return reject(err) | ||
resolve(data) | ||
}) | ||
}) | ||
} | ||
off(name) | ||
on(name, handler) | ||
} | ||
var isProcessing = false; | ||
@@ -103,19 +153,28 @@ var q = { | ||
payload, | ||
saturated: noop, | ||
unsaturated:noop, | ||
buffer: concurrency / 4, | ||
empty: noop, | ||
drain: noop, | ||
error: noop, | ||
started: false, | ||
paused: false, | ||
push (data, callback) { | ||
_insert(data, false, callback); | ||
if (Array.isArray(data)) { | ||
if (data.length === 0 && q.idle()) { | ||
// call drain immediately if there are no tasks | ||
return setImmediate(() => trigger('drain')); | ||
} | ||
return data.map(datum => _insert(datum, false, callback)) | ||
} | ||
return _insert(data, false, callback); | ||
}, | ||
kill () { | ||
q.drain = noop; | ||
off() | ||
q._tasks.empty(); | ||
}, | ||
unshift (data, callback) { | ||
_insert(data, true, callback); | ||
if (Array.isArray(data)) { | ||
if (data.length === 0 && q.idle()) { | ||
// call drain immediately if there are no tasks | ||
return setImmediate(() => trigger('drain')); | ||
} | ||
return data.map(datum => _insert(datum, true, callback)) | ||
} | ||
return _insert(data, true, callback); | ||
}, | ||
@@ -146,10 +205,10 @@ remove (testFn) { | ||
if (q._tasks.length === 0) { | ||
q.empty(); | ||
trigger('empty'); | ||
} | ||
if (numRunning === q.concurrency) { | ||
q.saturated(); | ||
trigger('saturated'); | ||
} | ||
var cb = onlyOnce(_next(tasks)); | ||
var cb = onlyOnce(_createCB(tasks)); | ||
_worker(data, cb); | ||
@@ -180,3 +239,26 @@ } | ||
}; | ||
// define these as fixed properties, so people get useful errors when updating | ||
Object.defineProperties(q, { | ||
saturated: { | ||
writable: false, | ||
value: eventMethod('saturated') | ||
}, | ||
unsaturated: { | ||
writable: false, | ||
value: eventMethod('unsaturated') | ||
}, | ||
empty: { | ||
writable: false, | ||
value: eventMethod('empty') | ||
}, | ||
drain: { | ||
writable: false, | ||
value: eventMethod('drain') | ||
}, | ||
error: { | ||
writable: false, | ||
value: eventMethod('error') | ||
}, | ||
}) | ||
return q; | ||
} |
@@ -36,3 +36,3 @@ import eachOfLimit from './internal/eachOfLimit' | ||
newObj[key] = result; | ||
next(); | ||
next(err); | ||
}); | ||
@@ -39,0 +39,0 @@ }, err => callback(err, newObj)); |
{ | ||
"name": "async-es", | ||
"description": "Higher-order functions and common patterns for asynchronous code", | ||
"version": "3.0.1-0", | ||
"version": "3.0.1", | ||
"main": "index.js", | ||
@@ -25,3 +25,3 @@ "author": "Caolan McMahon", | ||
"babel-eslint": "^8.2.6", | ||
"babel-minify": "^0.4.3", | ||
"babel-minify": "^0.5.0", | ||
"babel-plugin-add-module-exports": "^0.2.1", | ||
@@ -45,10 +45,14 @@ "babel-plugin-istanbul": "^2.0.1", | ||
"fs-extra": "^0.26.7", | ||
"gh-pages-deploy": "^0.5.0", | ||
"gh-pages-deploy": "^0.5.1", | ||
"jsdoc": "^3.4.0", | ||
"karma": "^2.0.5", | ||
"karma-browserify": "^5.3.0", | ||
"karma-edge-launcher": "^0.4.2", | ||
"karma-firefox-launcher": "^1.1.0", | ||
"karma-junit-reporter": "^1.2.0", | ||
"karma-mocha": "^1.2.0", | ||
"karma-mocha-reporter": "^2.2.0", | ||
"karma-safari-launcher": "^1.0.0", | ||
"mocha": "^5.2.0", | ||
"mocha-junit-reporter": "^1.18.0", | ||
"native-promise-only": "^0.8.0-a", | ||
@@ -83,3 +87,4 @@ "nyc": "^11.8.0", | ||
}, | ||
"module": "index.js", | ||
"sideEffects": false | ||
} |
import setImmediate from './setImmediate'; | ||
import queue from './queue'; | ||
import Heap from './internal/Heap'; | ||
@@ -31,2 +32,4 @@ /** | ||
q._tasks = new Heap(); | ||
// Override push to accept second parameter representing priority | ||
@@ -41,3 +44,3 @@ q.push = function(data, priority = 0, callback = () => {}) { | ||
} | ||
if (data.length === 0) { | ||
if (data.length === 0 && q.idle()) { | ||
// call drain immediately if there are no tasks | ||
@@ -47,7 +50,2 @@ return setImmediate(() => q.drain()); | ||
var nextNode = q._tasks.head; | ||
while (nextNode && priority >= nextNode.priority) { | ||
nextNode = nextNode.next; | ||
} | ||
for (var i = 0, l = data.length; i < l; i++) { | ||
@@ -60,8 +58,5 @@ var item = { | ||
if (nextNode) { | ||
q._tasks.insertBefore(nextNode, item); | ||
} else { | ||
q._tasks.push(item); | ||
} | ||
q._tasks.push(item); | ||
} | ||
setImmediate(q.process); | ||
@@ -68,0 +63,0 @@ }; |
54
queue.js
@@ -21,2 +21,5 @@ import queue from './internal/queue'; | ||
* `queue` is created to alter the concurrency on-the-fly. | ||
* @property {number} payload - an integer that specifies how many items are | ||
* passed to the worker function at a time. only applies if this is a | ||
* [cargo]{@link module:ControlFlow.cargo} object | ||
* @property {Function} push - add a new task to the `queue`. Calls `callback` | ||
@@ -34,16 +37,22 @@ * once the `worker` has finished processing the task. Instead of a single task, | ||
* `function ({data, priority}) {}` and returns a Boolean. | ||
* @property {Function} saturated - a callback that is called when the number of | ||
* running workers hits the `concurrency` limit, and further tasks will be | ||
* queued. | ||
* @property {Function} unsaturated - a callback that is called when the number | ||
* of running workers is less than the `concurrency` & `buffer` limits, and | ||
* further tasks will not be queued. | ||
* @property {Function} saturated - a function that sets a callback that is | ||
* called when the number of running workers hits the `concurrency` limit, and | ||
* further tasks will be queued. If the callback is omitted, `q.saturated()` | ||
* returns a promise for the next occurrence. | ||
* @property {Function} unsaturated - a function that sets a callback that is | ||
* called when the number of running workers is less than the `concurrency` & | ||
* `buffer` limits, and further tasks will not be queued. If the callback is | ||
* omitted, `q.unsaturated()` returns a promise for the next occurrence. | ||
* @property {number} buffer - A minimum threshold buffer in order to say that | ||
* the `queue` is `unsaturated`. | ||
* @property {Function} empty - a callback that is called when the last item | ||
* from the `queue` is given to a `worker`. | ||
* @property {Function} drain - a callback that is called when the last item | ||
* from the `queue` has returned from the `worker`. | ||
* @property {Function} error - a callback that is called when a task errors. | ||
* Has the signature `function(error, task)`. | ||
* @property {Function} empty - a function that sets a callback that is called | ||
* when the last item from the `queue` is given to a `worker`. If the callback | ||
* is omitted, `q.empty()` returns a promise for the next occurrence. | ||
* @property {Function} drain - a function that sets a callback that is called | ||
* when the last item from the `queue` has returned from the `worker`. If the | ||
* callback is omitted, `q.drain()` returns a promise for the next occurrence. | ||
* @property {Function} error - a function that sets a callback that is called | ||
* when a task errors. Has the signature `function(error, task)`. If the | ||
* callback is omitted, `error()` returns a promise that rejects on the next | ||
* error. | ||
* @property {boolean} paused - a boolean for determining whether the queue is | ||
@@ -70,2 +79,8 @@ * in a paused state. | ||
* } | ||
* | ||
* q.drain(() => { | ||
* console.log('all done') | ||
* }) | ||
* // or | ||
* await q.drain() | ||
*/ | ||
@@ -102,10 +117,12 @@ | ||
* // assign a callback | ||
* q.drain = function() { | ||
* q.drain(function() { | ||
* console.log('all items have been processed'); | ||
* }; | ||
* }); | ||
* // or await the end | ||
* await q.drain() | ||
* | ||
* // assign an error callback | ||
* q.error = function(err, task) { | ||
* q.error(function(err, task) { | ||
* console.error('task experienced an error'); | ||
* }; | ||
* }); | ||
* | ||
@@ -116,5 +133,4 @@ * // add some items to the queue | ||
* }); | ||
* q.push({name: 'bar'}, function (err) { | ||
* console.log('finished processing bar'); | ||
* }); | ||
* // callback is optional | ||
* q.push({name: 'bar'}); | ||
* | ||
@@ -121,0 +137,0 @@ * // add some items to the queue (batch-wise) |
@@ -47,10 +47,14 @@ import initialParams from './internal/initialParams'; | ||
args.push((error, ...cbArgs) => { | ||
let retVal = {}; | ||
if (error) { | ||
return reflectCallback(null, { error }); | ||
retVal.error = error; | ||
} | ||
var value = cbArgs; | ||
if (cbArgs.length <= 1) { | ||
[value] = cbArgs | ||
if (cbArgs.length > 0){ | ||
var value = cbArgs; | ||
if (cbArgs.length <= 1) { | ||
[value] = cbArgs; | ||
} | ||
retVal.value = value; | ||
} | ||
reflectCallback(null, { value }); | ||
reflectCallback(null, retVal); | ||
}); | ||
@@ -57,0 +61,0 @@ |
@@ -125,3 +125,3 @@ import wrapAsync from './internal/wrapAsync'; | ||
options.errorFilter(err))) { | ||
setTimeout(retryAttempt, options.intervalFunc(attempt)); | ||
setTimeout(retryAttempt, options.intervalFunc(attempt - 1)); | ||
} else { | ||
@@ -128,0 +128,0 @@ callback(err, ...args); |
@@ -58,3 +58,3 @@ import map from './map'; | ||
if (err) return iterCb(err); | ||
iterCb(null, {value: x, criteria}); | ||
iterCb(err, {value: x, criteria}); | ||
}); | ||
@@ -61,0 +61,0 @@ }, (err, results) => { |
@@ -48,2 +48,4 @@ import eachSeries from './eachSeries'; | ||
wrapAsync(task)((err, ...args) => { | ||
if (err === false) return taskCb(err); | ||
if (args.length < 2) { | ||
@@ -50,0 +52,0 @@ [result] = args; |
@@ -43,3 +43,3 @@ import onlyOnce from './internal/onlyOnce'; | ||
var _test = wrapAsync(test); | ||
var results | ||
var results = []; | ||
@@ -46,0 +46,0 @@ function next(err, ...rest) { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
259561
133
5939
0
0
42