| 1 |
(function (global, factory) { |
| 2 |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : |
| 3 |
typeof define === 'function' && define.amd ? define(['exports'], factory) : |
| 4 |
(factory((global.async = global.async || {}))); |
| 5 |
}(this, (function (exports) { 'use strict'; |
| 6 |
|
| 7 |
function slice(arrayLike, start) { |
| 8 |
start = start|0; |
| 9 |
var newLen = Math.max(arrayLike.length - start, 0); |
| 10 |
var newArr = Array(newLen); |
| 11 |
for(var idx = 0; idx < newLen; idx++) { |
| 12 |
newArr[idx] = arrayLike[start + idx]; |
| 13 |
} |
| 14 |
return newArr; |
| 15 |
} |
| 16 |
|
| 17 |
var initialParams = function (fn) { |
| 18 |
return function (/*...args, callback*/) { |
| 19 |
var args = slice(arguments); |
| 20 |
var callback = args.pop(); |
| 21 |
fn.call(this, args, callback); |
| 22 |
}; |
| 23 |
}; |
| 24 |
|
| 25 |
/** |
| 26 |
* Checks if `value` is the |
| 27 |
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) |
| 28 |
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) |
| 29 |
* |
| 30 |
* @static |
| 31 |
* @memberOf _ |
| 32 |
* @since 0.1.0 |
| 33 |
* @category Lang |
| 34 |
* @param {*} value The value to check. |
| 35 |
* @returns {boolean} Returns `true` if `value` is an object, else `false`. |
| 36 |
* @example |
| 37 |
* |
| 38 |
* _.isObject({}); |
| 39 |
* // => true |
| 40 |
* |
| 41 |
* _.isObject([1, 2, 3]); |
| 42 |
* // => true |
| 43 |
* |
| 44 |
* _.isObject(_.noop); |
| 45 |
* // => true |
| 46 |
* |
| 47 |
* _.isObject(null); |
| 48 |
* // => false |
| 49 |
*/ |
| 50 |
function isObject(value) { |
| 51 |
var type = typeof value; |
| 52 |
return value != null && (type == 'object' || type == 'function'); |
| 53 |
} |
| 54 |
|
| 55 |
var hasSetImmediate = typeof setImmediate === 'function' && setImmediate; |
| 56 |
var hasNextTick = typeof process === 'object' && typeof process.nextTick === 'function'; |
| 57 |
|
| 58 |
function fallback(fn) { |
| 59 |
setTimeout(fn, 0); |
| 60 |
} |
| 61 |
|
| 62 |
function wrap(defer) { |
| 63 |
return function (fn/*, ...args*/) { |
| 64 |
var args = slice(arguments, 1); |
| 65 |
defer(function () { |
| 66 |
fn.apply(null, args); |
| 67 |
}); |
| 68 |
}; |
| 69 |
} |
| 70 |
|
| 71 |
var _defer; |
| 72 |
|
| 73 |
if (hasSetImmediate) { |
| 74 |
_defer = setImmediate; |
| 75 |
} else if (hasNextTick) { |
| 76 |
_defer = process.nextTick; |
| 77 |
} else { |
| 78 |
_defer = fallback; |
| 79 |
} |
| 80 |
|
| 81 |
var setImmediate$1 = wrap(_defer); |
| 82 |
|
| 83 |
/** |
| 84 |
* Take a sync function and make it async, passing its return value to a |
| 85 |
* callback. This is useful for plugging sync functions into a waterfall, |
| 86 |
* series, or other async functions. Any arguments passed to the generated |
| 87 |
* function will be passed to the wrapped function (except for the final |
| 88 |
* callback argument). Errors thrown will be passed to the callback. |
| 89 |
* |
| 90 |
* If the function passed to `asyncify` returns a Promise, that promises's |
| 91 |
* resolved/rejected state will be used to call the callback, rather than simply |
| 92 |
* the synchronous return value. |
| 93 |
* |
| 94 |
* This also means you can asyncify ES2017 `async` functions. |
| 95 |
* |
| 96 |
* @name asyncify |
| 97 |
* @static |
| 98 |
* @memberOf module:Utils |
| 99 |
* @method |
| 100 |
* @alias wrapSync |
| 101 |
* @category Util |
| 102 |
* @param {Function} func - The synchronous function, or Promise-returning |
| 103 |
* function to convert to an {@link AsyncFunction}. |
| 104 |
* @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be |
| 105 |
* invoked with `(args..., callback)`. |
| 106 |
* @example |
| 107 |
* |
| 108 |
* // passing a regular synchronous function |
| 109 |
* async.waterfall([ |
| 110 |
* async.apply(fs.readFile, filename, "utf8"), |
| 111 |
* async.asyncify(JSON.parse), |
| 112 |
* function (data, next) { |
| 113 |
* // data is the result of parsing the text. |
| 114 |
* // If there was a parsing error, it would have been caught. |
| 115 |
* } |
| 116 |
* ], callback); |
| 117 |
* |
| 118 |
* // passing a function returning a promise |
| 119 |
* async.waterfall([ |
| 120 |
* async.apply(fs.readFile, filename, "utf8"), |
| 121 |
* async.asyncify(function (contents) { |
| 122 |
* return db.model.create(contents); |
| 123 |
* }), |
| 124 |
* function (model, next) { |
| 125 |
* // `model` is the instantiated model object. |
| 126 |
* // If there was an error, this function would be skipped. |
| 127 |
* } |
| 128 |
* ], callback); |
| 129 |
* |
| 130 |
* // es2017 example, though `asyncify` is not needed if your JS environment |
| 131 |
* // supports async functions out of the box |
| 132 |
* var q = async.queue(async.asyncify(async function(file) { |
| 133 |
* var intermediateStep = await processFile(file); |
| 134 |
* return await somePromise(intermediateStep) |
| 135 |
* })); |
| 136 |
* |
| 137 |
* q.push(files); |
| 138 |
*/ |
| 139 |
function asyncify(func) { |
| 140 |
return initialParams(function (args, callback) { |
| 141 |
var result; |
| 142 |
try { |
| 143 |
result = func.apply(this, args); |
| 144 |
} catch (e) { |
| 145 |
return callback(e); |
| 146 |
} |
| 147 |
// if result is Promise object |
| 148 |
if (isObject(result) && typeof result.then === 'function') { |
| 149 |
result.then(function(value) { |
| 150 |
invokeCallback(callback, null, value); |
| 151 |
}, function(err) { |
| 152 |
invokeCallback(callback, err.message ? err : new Error(err)); |
| 153 |
}); |
| 154 |
} else { |
| 155 |
callback(null, result); |
| 156 |
} |
| 157 |
}); |
| 158 |
} |
| 159 |
|
| 160 |
function invokeCallback(callback, error, value) { |
| 161 |
try { |
| 162 |
callback(error, value); |
| 163 |
} catch (e) { |
| 164 |
setImmediate$1(rethrow, e); |
| 165 |
} |
| 166 |
} |
| 167 |
|
| 168 |
function rethrow(error) { |
| 169 |
throw error; |
| 170 |
} |
| 171 |
|
| 172 |
var supportsSymbol = typeof Symbol === 'function'; |
| 173 |
|
| 174 |
function isAsync(fn) { |
| 175 |
return supportsSymbol && fn[Symbol.toStringTag] === 'AsyncFunction'; |
| 176 |
} |
| 177 |
|
| 178 |
function wrapAsync(asyncFn) { |
| 179 |
return isAsync(asyncFn) ? asyncify(asyncFn) : asyncFn; |
| 180 |
} |
| 181 |
|
| 182 |
function applyEach$1(eachfn) { |
| 183 |
return function(fns/*, ...args*/) { |
| 184 |
var args = slice(arguments, 1); |
| 185 |
var go = initialParams(function(args, callback) { |
| 186 |
var that = this; |
| 187 |
return eachfn(fns, function (fn, cb) { |
| 188 |
wrapAsync(fn).apply(that, args.concat(cb)); |
| 189 |
}, callback); |
| 190 |
}); |
| 191 |
if (args.length) { |
| 192 |
return go.apply(this, args); |
| 193 |
} |
| 194 |
else { |
| 195 |
return go; |
| 196 |
} |
| 197 |
}; |
| 198 |
} |
| 199 |
|
| 200 |
/** Detect free variable `global` from Node.js. */ |
| 201 |
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; |
| 202 |
|
| 203 |
/** Detect free variable `self`. */ |
| 204 |
var freeSelf = typeof self == 'object' && self && self.Object === Object && self; |
| 205 |
|
| 206 |
/** Used as a reference to the global object. */ |
| 207 |
var root = freeGlobal || freeSelf || Function('return this')(); |
| 208 |
|
| 209 |
/** Built-in value references. */ |
| 210 |
var Symbol$1 = root.Symbol; |
| 211 |
|
| 212 |
/** Used for built-in method references. */ |
| 213 |
var objectProto = Object.prototype; |
| 214 |
|
| 215 |
/** Used to check objects for own properties. */ |
| 216 |
var hasOwnProperty = objectProto.hasOwnProperty; |
| 217 |
|
| 218 |
/** |
| 219 |
* Used to resolve the |
| 220 |
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) |
| 221 |
* of values. |
| 222 |
*/ |
| 223 |
var nativeObjectToString = objectProto.toString; |
| 224 |
|
| 225 |
/** Built-in value references. */ |
| 226 |
var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined; |
| 227 |
|
| 228 |
/** |
| 229 |
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. |
| 230 |
* |
| 231 |
* @private |
| 232 |
* @param {*} value The value to query. |
| 233 |
* @returns {string} Returns the raw `toStringTag`. |
| 234 |
*/ |
| 235 |
function getRawTag(value) { |
| 236 |
var isOwn = hasOwnProperty.call(value, symToStringTag$1), |
| 237 |
tag = value[symToStringTag$1]; |
| 238 |
|
| 239 |
try { |
| 240 |
value[symToStringTag$1] = undefined; |
| 241 |
var unmasked = true; |
| 242 |
} catch (e) {} |
| 243 |
|
| 244 |
var result = nativeObjectToString.call(value); |
| 245 |
if (unmasked) { |
| 246 |
if (isOwn) { |
| 247 |
value[symToStringTag$1] = tag; |
| 248 |
} else { |
| 249 |
delete value[symToStringTag$1]; |
| 250 |
} |
| 251 |
} |
| 252 |
return result; |
| 253 |
} |
| 254 |
|
| 255 |
/** Used for built-in method references. */ |
| 256 |
var objectProto$1 = Object.prototype; |
| 257 |
|
| 258 |
/** |
| 259 |
* Used to resolve the |
| 260 |
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) |
| 261 |
* of values. |
| 262 |
*/ |
| 263 |
var nativeObjectToString$1 = objectProto$1.toString; |
| 264 |
|
| 265 |
/** |
| 266 |
* Converts `value` to a string using `Object.prototype.toString`. |
| 267 |
* |
| 268 |
* @private |
| 269 |
* @param {*} value The value to convert. |
| 270 |
* @returns {string} Returns the converted string. |
| 271 |
*/ |
| 272 |
function objectToString(value) { |
| 273 |
return nativeObjectToString$1.call(value); |
| 274 |
} |
| 275 |
|
| 276 |
/** `Object#toString` result references. */ |
| 277 |
var nullTag = '[object Null]'; |
| 278 |
var undefinedTag = '[object Undefined]'; |
| 279 |
|
| 280 |
/** Built-in value references. */ |
| 281 |
var symToStringTag = Symbol$1 ? Symbol$1.toStringTag : undefined; |
| 282 |
|
| 283 |
/** |
| 284 |
* The base implementation of `getTag` without fallbacks for buggy environments. |
| 285 |
* |
| 286 |
* @private |
| 287 |
* @param {*} value The value to query. |
| 288 |
* @returns {string} Returns the `toStringTag`. |
| 289 |
*/ |
| 290 |
function baseGetTag(value) { |
| 291 |
if (value == null) { |
| 292 |
return value === undefined ? undefinedTag : nullTag; |
| 293 |
} |
| 294 |
value = Object(value); |
| 295 |
return (symToStringTag && symToStringTag in value) |
| 296 |
? getRawTag(value) |
| 297 |
: objectToString(value); |
| 298 |
} |
| 299 |
|
| 300 |
/** `Object#toString` result references. */ |
| 301 |
var asyncTag = '[object AsyncFunction]'; |
| 302 |
var funcTag = '[object Function]'; |
| 303 |
var genTag = '[object GeneratorFunction]'; |
| 304 |
var proxyTag = '[object Proxy]'; |
| 305 |
|
| 306 |
/** |
| 307 |
* Checks if `value` is classified as a `Function` object. |
| 308 |
* |
| 309 |
* @static |
| 310 |
* @memberOf _ |
| 311 |
* @since 0.1.0 |
| 312 |
* @category Lang |
| 313 |
* @param {*} value The value to check. |
| 314 |
* @returns {boolean} Returns `true` if `value` is a function, else `false`. |
| 315 |
* @example |
| 316 |
* |
| 317 |
* _.isFunction(_); |
| 318 |
* // => true |
| 319 |
* |
| 320 |
* _.isFunction(/abc/); |
| 321 |
* // => false |
| 322 |
*/ |
| 323 |
function isFunction(value) { |
| 324 |
if (!isObject(value)) { |
| 325 |
return false; |
| 326 |
} |
| 327 |
// The use of `Object#toString` avoids issues with the `typeof` operator |
| 328 |
// in Safari 9 which returns 'object' for typed arrays and other constructors. |
| 329 |
var tag = baseGetTag(value); |
| 330 |
return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; |
| 331 |
} |
| 332 |
|
| 333 |
/** Used as references for various `Number` constants. */ |
| 334 |
var MAX_SAFE_INTEGER = 9007199254740991; |
| 335 |
|
| 336 |
/** |
| 337 |
* Checks if `value` is a valid array-like length. |
| 338 |
* |
| 339 |
* **Note:** This method is loosely based on |
| 340 |
* [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). |
| 341 |
* |
| 342 |
* @static |
| 343 |
* @memberOf _ |
| 344 |
* @since 4.0.0 |
| 345 |
* @category Lang |
| 346 |
* @param {*} value The value to check. |
| 347 |
* @returns {boolean} Returns `true` if `value` is a valid length, else `false`. |
| 348 |
* @example |
| 349 |
* |
| 350 |
* _.isLength(3); |
| 351 |
* // => true |
| 352 |
* |
| 353 |
* _.isLength(Number.MIN_VALUE); |
| 354 |
* // => false |
| 355 |
* |
| 356 |
* _.isLength(Infinity); |
| 357 |
* // => false |
| 358 |
* |
| 359 |
* _.isLength('3'); |
| 360 |
* // => false |
| 361 |
*/ |
| 362 |
function isLength(value) { |
| 363 |
return typeof value == 'number' && |
| 364 |
value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; |
| 365 |
} |
| 366 |
|
| 367 |
/** |
| 368 |
* Checks if `value` is array-like. A value is considered array-like if it's |
| 369 |
* not a function and has a `value.length` that's an integer greater than or |
| 370 |
* equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. |
| 371 |
* |
| 372 |
* @static |
| 373 |
* @memberOf _ |
| 374 |
* @since 4.0.0 |
| 375 |
* @category Lang |
| 376 |
* @param {*} value The value to check. |
| 377 |
* @returns {boolean} Returns `true` if `value` is array-like, else `false`. |
| 378 |
* @example |
| 379 |
* |
| 380 |
* _.isArrayLike([1, 2, 3]); |
| 381 |
* // => true |
| 382 |
* |
| 383 |
* _.isArrayLike(document.body.children); |
| 384 |
* // => true |
| 385 |
* |
| 386 |
* _.isArrayLike('abc'); |
| 387 |
* // => true |
| 388 |
* |
| 389 |
* _.isArrayLike(_.noop); |
| 390 |
* // => false |
| 391 |
*/ |
| 392 |
function isArrayLike(value) { |
| 393 |
return value != null && isLength(value.length) && !isFunction(value); |
| 394 |
} |
| 395 |
|
| 396 |
// A temporary value used to identify if the loop should be broken. |
| 397 |
// See #1064, #1293 |
| 398 |
var breakLoop = {}; |
| 399 |
|
| 400 |
/** |
| 401 |
* This method returns `undefined`. |
| 402 |
* |
| 403 |
* @static |
| 404 |
* @memberOf _ |
| 405 |
* @since 2.3.0 |
| 406 |
* @category Util |
| 407 |
* @example |
| 408 |
* |
| 409 |
* _.times(2, _.noop); |
| 410 |
* // => [undefined, undefined] |
| 411 |
*/ |
| 412 |
function noop() { |
| 413 |
// No operation performed. |
| 414 |
} |
| 415 |
|
| 416 |
function once(fn) { |
| 417 |
return function () { |
| 418 |
if (fn === null) return; |
| 419 |
var callFn = fn; |
| 420 |
fn = null; |
| 421 |
callFn.apply(this, arguments); |
| 422 |
}; |
| 423 |
} |
| 424 |
|
| 425 |
var iteratorSymbol = typeof Symbol === 'function' && Symbol.iterator; |
| 426 |
|
| 427 |
var getIterator = function (coll) { |
| 428 |
return iteratorSymbol && coll[iteratorSymbol] && coll[iteratorSymbol](); |
| 429 |
}; |
| 430 |
|
| 431 |
/** |
| 432 |
* The base implementation of `_.times` without support for iteratee shorthands |
| 433 |
* or max array length checks. |
| 434 |
* |
| 435 |
* @private |
| 436 |
* @param {number} n The number of times to invoke `iteratee`. |
| 437 |
* @param {Function} iteratee The function invoked per iteration. |
| 438 |
* @returns {Array} Returns the array of results. |
| 439 |
*/ |
| 440 |
function baseTimes(n, iteratee) { |
| 441 |
var index = -1, |
| 442 |
result = Array(n); |
| 443 |
|
| 444 |
while (++index < n) { |
| 445 |
result[index] = iteratee(index); |
| 446 |
} |
| 447 |
return result; |
| 448 |
} |
| 449 |
|
| 450 |
/** |
| 451 |
* Checks if `value` is object-like. A value is object-like if it's not `null` |
| 452 |
* and has a `typeof` result of "object". |
| 453 |
* |
| 454 |
* @static |
| 455 |
* @memberOf _ |
| 456 |
* @since 4.0.0 |
| 457 |
* @category Lang |
| 458 |
* @param {*} value The value to check. |
| 459 |
* @returns {boolean} Returns `true` if `value` is object-like, else `false`. |
| 460 |
* @example |
| 461 |
* |
| 462 |
* _.isObjectLike({}); |
| 463 |
* // => true |
| 464 |
* |
| 465 |
* _.isObjectLike([1, 2, 3]); |
| 466 |
* // => true |
| 467 |
* |
| 468 |
* _.isObjectLike(_.noop); |
| 469 |
* // => false |
| 470 |
* |
| 471 |
* _.isObjectLike(null); |
| 472 |
* // => false |
| 473 |
*/ |
| 474 |
function isObjectLike(value) { |
| 475 |
return value != null && typeof value == 'object'; |
| 476 |
} |
| 477 |
|
| 478 |
/** `Object#toString` result references. */ |
| 479 |
var argsTag = '[object Arguments]'; |
| 480 |
|
| 481 |
/** |
| 482 |
* The base implementation of `_.isArguments`. |
| 483 |
* |
| 484 |
* @private |
| 485 |
* @param {*} value The value to check. |
| 486 |
* @returns {boolean} Returns `true` if `value` is an `arguments` object, |
| 487 |
*/ |
| 488 |
function baseIsArguments(value) { |
| 489 |
return isObjectLike(value) && baseGetTag(value) == argsTag; |
| 490 |
} |
| 491 |
|
| 492 |
/** Used for built-in method references. */ |
| 493 |
var objectProto$3 = Object.prototype; |
| 494 |
|
| 495 |
/** Used to check objects for own properties. */ |
| 496 |
var hasOwnProperty$2 = objectProto$3.hasOwnProperty; |
| 497 |
|
| 498 |
/** Built-in value references. */ |
| 499 |
var propertyIsEnumerable = objectProto$3.propertyIsEnumerable; |
| 500 |
|
| 501 |
/** |
| 502 |
* Checks if `value` is likely an `arguments` object. |
| 503 |
* |
| 504 |
* @static |
| 505 |
* @memberOf _ |
| 506 |
* @since 0.1.0 |
| 507 |
* @category Lang |
| 508 |
* @param {*} value The value to check. |
| 509 |
* @returns {boolean} Returns `true` if `value` is an `arguments` object, |
| 510 |
* else `false`. |
| 511 |
* @example |
| 512 |
* |
| 513 |
* _.isArguments(function() { return arguments; }()); |
| 514 |
* // => true |
| 515 |
* |
| 516 |
* _.isArguments([1, 2, 3]); |
| 517 |
* // => false |
| 518 |
*/ |
| 519 |
var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { |
| 520 |
return isObjectLike(value) && hasOwnProperty$2.call(value, 'callee') && |
| 521 |
!propertyIsEnumerable.call(value, 'callee'); |
| 522 |
}; |
| 523 |
|
| 524 |
/** |
| 525 |
* Checks if `value` is classified as an `Array` object. |
| 526 |
* |
| 527 |
* @static |
| 528 |
* @memberOf _ |
| 529 |
* @since 0.1.0 |
| 530 |
* @category Lang |
| 531 |
* @param {*} value The value to check. |
| 532 |
* @returns {boolean} Returns `true` if `value` is an array, else `false`. |
| 533 |
* @example |
| 534 |
* |
| 535 |
* _.isArray([1, 2, 3]); |
| 536 |
* // => true |
| 537 |
* |
| 538 |
* _.isArray(document.body.children); |
| 539 |
* // => false |
| 540 |
* |
| 541 |
* _.isArray('abc'); |
| 542 |
* // => false |
| 543 |
* |
| 544 |
* _.isArray(_.noop); |
| 545 |
* // => false |
| 546 |
*/ |
| 547 |
var isArray = Array.isArray; |
| 548 |
|
| 549 |
/** |
| 550 |
* This method returns `false`. |
| 551 |
* |
| 552 |
* @static |
| 553 |
* @memberOf _ |
| 554 |
* @since 4.13.0 |
| 555 |
* @category Util |
| 556 |
* @returns {boolean} Returns `false`. |
| 557 |
* @example |
| 558 |
* |
| 559 |
* _.times(2, _.stubFalse); |
| 560 |
* // => [false, false] |
| 561 |
*/ |
| 562 |
function stubFalse() { |
| 563 |
return false; |
| 564 |
} |
| 565 |
|
| 566 |
/** Detect free variable `exports`. */ |
| 567 |
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; |
| 568 |
|
| 569 |
/** Detect free variable `module`. */ |
| 570 |
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; |
| 571 |
|
| 572 |
/** Detect the popular CommonJS extension `module.exports`. */ |
| 573 |
var moduleExports = freeModule && freeModule.exports === freeExports; |
| 574 |
|
| 575 |
/** Built-in value references. */ |
| 576 |
var Buffer = moduleExports ? root.Buffer : undefined; |
| 577 |
|
| 578 |
/* Built-in method references for those with the same name as other `lodash` methods. */ |
| 579 |
var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined; |
| 580 |
|
| 581 |
/** |
| 582 |
* Checks if `value` is a buffer. |
| 583 |
* |
| 584 |
* @static |
| 585 |
* @memberOf _ |
| 586 |
* @since 4.3.0 |
| 587 |
* @category Lang |
| 588 |
* @param {*} value The value to check. |
| 589 |
* @returns {boolean} Returns `true` if `value` is a buffer, else `false`. |
| 590 |
* @example |
| 591 |
* |
| 592 |
* _.isBuffer(new Buffer(2)); |
| 593 |
* // => true |
| 594 |
* |
| 595 |
* _.isBuffer(new Uint8Array(2)); |
| 596 |
* // => false |
| 597 |
*/ |
| 598 |
var isBuffer = nativeIsBuffer || stubFalse; |
| 599 |
|
| 600 |
/** Used as references for various `Number` constants. */ |
| 601 |
var MAX_SAFE_INTEGER$1 = 9007199254740991; |
| 602 |
|
| 603 |
/** Used to detect unsigned integer values. */ |
| 604 |
var reIsUint = /^(?:0|[1-9]\d*)$/; |
| 605 |
|
| 606 |
/** |
| 607 |
* Checks if `value` is a valid array-like index. |
| 608 |
* |
| 609 |
* @private |
| 610 |
* @param {*} value The value to check. |
| 611 |
* @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. |
| 612 |
* @returns {boolean} Returns `true` if `value` is a valid index, else `false`. |
| 613 |
*/ |
| 614 |
function isIndex(value, length) { |
| 615 |
length = length == null ? MAX_SAFE_INTEGER$1 : length; |
| 616 |
return !!length && |
| 617 |
(typeof value == 'number' || reIsUint.test(value)) && |
| 618 |
(value > -1 && value % 1 == 0 && value < length); |
| 619 |
} |
| 620 |
|
| 621 |
/** `Object#toString` result references. */ |
| 622 |
var argsTag$1 = '[object Arguments]'; |
| 623 |
var arrayTag = '[object Array]'; |
| 624 |
var boolTag = '[object Boolean]'; |
| 625 |
var dateTag = '[object Date]'; |
| 626 |
var errorTag = '[object Error]'; |
| 627 |
var funcTag$1 = '[object Function]'; |
| 628 |
var mapTag = '[object Map]'; |
| 629 |
var numberTag = '[object Number]'; |
| 630 |
var objectTag = '[object Object]'; |
| 631 |
var regexpTag = '[object RegExp]'; |
| 632 |
var setTag = '[object Set]'; |
| 633 |
var stringTag = '[object String]'; |
| 634 |
var weakMapTag = '[object WeakMap]'; |
| 635 |
|
| 636 |
var arrayBufferTag = '[object ArrayBuffer]'; |
| 637 |
var dataViewTag = '[object DataView]'; |
| 638 |
var float32Tag = '[object Float32Array]'; |
| 639 |
var float64Tag = '[object Float64Array]'; |
| 640 |
var int8Tag = '[object Int8Array]'; |
| 641 |
var int16Tag = '[object Int16Array]'; |
| 642 |
var int32Tag = '[object Int32Array]'; |
| 643 |
var uint8Tag = '[object Uint8Array]'; |
| 644 |
var uint8ClampedTag = '[object Uint8ClampedArray]'; |
| 645 |
var uint16Tag = '[object Uint16Array]'; |
| 646 |
var uint32Tag = '[object Uint32Array]'; |
| 647 |
|
| 648 |
/** Used to identify `toStringTag` values of typed arrays. */ |
| 649 |
var typedArrayTags = {}; |
| 650 |
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = |
| 651 |
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = |
| 652 |
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = |
| 653 |
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = |
| 654 |
typedArrayTags[uint32Tag] = true; |
| 655 |
typedArrayTags[argsTag$1] = typedArrayTags[arrayTag] = |
| 656 |
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = |
| 657 |
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = |
| 658 |
typedArrayTags[errorTag] = typedArrayTags[funcTag$1] = |
| 659 |
typedArrayTags[mapTag] = typedArrayTags[numberTag] = |
| 660 |
typedArrayTags[objectTag] = typedArrayTags[regexpTag] = |
| 661 |
typedArrayTags[setTag] = typedArrayTags[stringTag] = |
| 662 |
typedArrayTags[weakMapTag] = false; |
| 663 |
|
| 664 |
/** |
| 665 |
* The base implementation of `_.isTypedArray` without Node.js optimizations. |
| 666 |
* |
| 667 |
* @private |
| 668 |
* @param {*} value The value to check. |
| 669 |
* @returns {boolean} Returns `true` if `value` is a typed array, else `false`. |
| 670 |
*/ |
| 671 |
function baseIsTypedArray(value) { |
| 672 |
return isObjectLike(value) && |
| 673 |
isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; |
| 674 |
} |
| 675 |
|
| 676 |
/** |
| 677 |
* The base implementation of `_.unary` without support for storing metadata. |
| 678 |
* |
| 679 |
* @private |
| 680 |
* @param {Function} func The function to cap arguments for. |
| 681 |
* @returns {Function} Returns the new capped function. |
| 682 |
*/ |
| 683 |
function baseUnary(func) { |
| 684 |
return function(value) { |
| 685 |
return func(value); |
| 686 |
}; |
| 687 |
} |
| 688 |
|
| 689 |
/** Detect free variable `exports`. */ |
| 690 |
var freeExports$1 = typeof exports == 'object' && exports && !exports.nodeType && exports; |
| 691 |
|
| 692 |
/** Detect free variable `module`. */ |
| 693 |
var freeModule$1 = freeExports$1 && typeof module == 'object' && module && !module.nodeType && module; |
| 694 |
|
| 695 |
/** Detect the popular CommonJS extension `module.exports`. */ |
| 696 |
var moduleExports$1 = freeModule$1 && freeModule$1.exports === freeExports$1; |
| 697 |
|
| 698 |
/** Detect free variable `process` from Node.js. */ |
| 699 |
var freeProcess = moduleExports$1 && freeGlobal.process; |
| 700 |
|
| 701 |
/** Used to access faster Node.js helpers. */ |
| 702 |
var nodeUtil = (function() { |
| 703 |
try { |
| 704 |
return freeProcess && freeProcess.binding('util'); |
| 705 |
} catch (e) {} |
| 706 |
}()); |
| 707 |
|
| 708 |
/* Node.js helper references. */ |
| 709 |
var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; |
| 710 |
|
| 711 |
/** |
| 712 |
* Checks if `value` is classified as a typed array. |
| 713 |
* |
| 714 |
* @static |
| 715 |
* @memberOf _ |
| 716 |
* @since 3.0.0 |
| 717 |
* @category Lang |
| 718 |
* @param {*} value The value to check. |
| 719 |
* @returns {boolean} Returns `true` if `value` is a typed array, else `false`. |
| 720 |
* @example |
| 721 |
* |
| 722 |
* _.isTypedArray(new Uint8Array); |
| 723 |
* // => true |
| 724 |
* |
| 725 |
* _.isTypedArray([]); |
| 726 |
* // => false |
| 727 |
*/ |
| 728 |
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; |
| 729 |
|
| 730 |
/** Used for built-in method references. */ |
| 731 |
var objectProto$2 = Object.prototype; |
| 732 |
|
| 733 |
/** Used to check objects for own properties. */ |
| 734 |
var hasOwnProperty$1 = objectProto$2.hasOwnProperty; |
| 735 |
|
| 736 |
/** |
| 737 |
* Creates an array of the enumerable property names of the array-like `value`. |
| 738 |
* |
| 739 |
* @private |
| 740 |
* @param {*} value The value to query. |
| 741 |
* @param {boolean} inherited Specify returning inherited property names. |
| 742 |
* @returns {Array} Returns the array of property names. |
| 743 |
*/ |
| 744 |
function arrayLikeKeys(value, inherited) { |
| 745 |
var isArr = isArray(value), |
| 746 |
isArg = !isArr && isArguments(value), |
| 747 |
isBuff = !isArr && !isArg && isBuffer(value), |
| 748 |
isType = !isArr && !isArg && !isBuff && isTypedArray(value), |
| 749 |
skipIndexes = isArr || isArg || isBuff || isType, |
| 750 |
result = skipIndexes ? baseTimes(value.length, String) : [], |
| 751 |
length = result.length; |
| 752 |
|
| 753 |
for (var key in value) { |
| 754 |
if ((inherited || hasOwnProperty$1.call(value, key)) && |
| 755 |
!(skipIndexes && ( |
| 756 |
// Safari 9 has enumerable `arguments.length` in strict mode. |
| 757 |
key == 'length' || |
| 758 |
// Node.js 0.10 has enumerable non-index properties on buffers. |
| 759 |
(isBuff && (key == 'offset' || key == 'parent')) || |
| 760 |
// PhantomJS 2 has enumerable non-index properties on typed arrays. |
| 761 |
(isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || |
| 762 |
// Skip index properties. |
| 763 |
isIndex(key, length) |
| 764 |
))) { |
| 765 |
result.push(key); |
| 766 |
} |
| 767 |
} |
| 768 |
return result; |
| 769 |
} |
| 770 |
|
| 771 |
/** Used for built-in method references. */ |
| 772 |
var objectProto$5 = Object.prototype; |
| 773 |
|
| 774 |
/** |
| 775 |
* Checks if `value` is likely a prototype object. |
| 776 |
* |
| 777 |
* @private |
| 778 |
* @param {*} value The value to check. |
| 779 |
* @returns {boolean} Returns `true` if `value` is a prototype, else `false`. |
| 780 |
*/ |
| 781 |
function isPrototype(value) { |
| 782 |
var Ctor = value && value.constructor, |
| 783 |
proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto$5; |
| 784 |
|
| 785 |
return value === proto; |
| 786 |
} |
| 787 |
|
| 788 |
/** |
| 789 |
* Creates a unary function that invokes `func` with its argument transformed. |
| 790 |
* |
| 791 |
* @private |
| 792 |
* @param {Function} func The function to wrap. |
| 793 |
* @param {Function} transform The argument transform. |
| 794 |
* @returns {Function} Returns the new function. |
| 795 |
*/ |
| 796 |
function overArg(func, transform) { |
| 797 |
return function(arg) { |
| 798 |
return func(transform(arg)); |
| 799 |
}; |
| 800 |
} |
| 801 |
|
| 802 |
/* Built-in method references for those with the same name as other `lodash` methods. */ |
| 803 |
var nativeKeys = overArg(Object.keys, Object); |
| 804 |
|
| 805 |
/** Used for built-in method references. */ |
| 806 |
var objectProto$4 = Object.prototype; |
| 807 |
|
| 808 |
/** Used to check objects for own properties. */ |
| 809 |
var hasOwnProperty$3 = objectProto$4.hasOwnProperty; |
| 810 |
|
| 811 |
/** |
| 812 |
* The base implementation of `_.keys` which doesn't treat sparse arrays as dense. |
| 813 |
* |
| 814 |
* @private |
| 815 |
* @param {Object} object The object to query. |
| 816 |
* @returns {Array} Returns the array of property names. |
| 817 |
*/ |
| 818 |
function baseKeys(object) { |
| 819 |
if (!isPrototype(object)) { |
| 820 |
return nativeKeys(object); |
| 821 |
} |
| 822 |
var result = []; |
| 823 |
for (var key in Object(object)) { |
| 824 |
if (hasOwnProperty$3.call(object, key) && key != 'constructor') { |
| 825 |
result.push(key); |
| 826 |
} |
| 827 |
} |
| 828 |
return result; |
| 829 |
} |
| 830 |
|
| 831 |
/** |
| 832 |
* Creates an array of the own enumerable property names of `object`. |
| 833 |
* |
| 834 |
* **Note:** Non-object values are coerced to objects. See the |
| 835 |
* [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) |
| 836 |
* for more details. |
| 837 |
* |
| 838 |
* @static |
| 839 |
* @since 0.1.0 |
| 840 |
* @memberOf _ |
| 841 |
* @category Object |
| 842 |
* @param {Object} object The object to query. |
| 843 |
* @returns {Array} Returns the array of property names. |
| 844 |
* @example |
| 845 |
* |
| 846 |
* function Foo() { |
| 847 |
* this.a = 1; |
| 848 |
* this.b = 2; |
| 849 |
* } |
| 850 |
* |
| 851 |
* Foo.prototype.c = 3; |
| 852 |
* |
| 853 |
* _.keys(new Foo); |
| 854 |
* // => ['a', 'b'] (iteration order is not guaranteed) |
| 855 |
* |
| 856 |
* _.keys('hi'); |
| 857 |
* // => ['0', '1'] |
| 858 |
*/ |
| 859 |
function keys(object) { |
| 860 |
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); |
| 861 |
} |
| 862 |
|
| 863 |
function createArrayIterator(coll) { |
| 864 |
var i = -1; |
| 865 |
var len = coll.length; |
| 866 |
return function next() { |
| 867 |
return ++i < len ? {value: coll[i], key: i} : null; |
| 868 |
} |
| 869 |
} |
| 870 |
|
| 871 |
function createES2015Iterator(iterator) { |
| 872 |
var i = -1; |
| 873 |
return function next() { |
| 874 |
var item = iterator.next(); |
| 875 |
if (item.done) |
| 876 |
return null; |
| 877 |
i++; |
| 878 |
return {value: item.value, key: i}; |
| 879 |
} |
| 880 |
} |
| 881 |
|
| 882 |
function createObjectIterator(obj) { |
| 883 |
var okeys = keys(obj); |
| 884 |
var i = -1; |
| 885 |
var len = okeys.length; |
| 886 |
return function next() { |
| 887 |
var key = okeys[++i]; |
| 888 |
return i < len ? {value: obj[key], key: key} : null; |
| 889 |
}; |
| 890 |
} |
| 891 |
|
| 892 |
function iterator(coll) { |
| 893 |
if (isArrayLike(coll)) { |
| 894 |
return createArrayIterator(coll); |
| 895 |
} |
| 896 |
|
| 897 |
var iterator = getIterator(coll); |
| 898 |
return iterator ? createES2015Iterator(iterator) : createObjectIterator(coll); |
| 899 |
} |
| 900 |
|
| 901 |
function onlyOnce(fn) { |
| 902 |
return function() { |
| 903 |
if (fn === null) throw new Error("Callback was already called."); |
| 904 |
var callFn = fn; |
| 905 |
fn = null; |
| 906 |
callFn.apply(this, arguments); |
| 907 |
}; |
| 908 |
} |
| 909 |
|
| 910 |
function _eachOfLimit(limit) { |
| 911 |
return function (obj, iteratee, callback) { |
| 912 |
callback = once(callback || noop); |
| 913 |
if (limit <= 0 || !obj) { |
| 914 |
return callback(null); |
| 915 |
} |
| 916 |
var nextElem = iterator(obj); |
| 917 |
var done = false; |
| 918 |
var running = 0; |
| 919 |
|
| 920 |
function iterateeCallback(err, value) { |
| 921 |
running -= 1; |
| 922 |
if (err) { |
| 923 |
done = true; |
| 924 |
callback(err); |
| 925 |
} |
| 926 |
else if (value === breakLoop || (done && running <= 0)) { |
| 927 |
done = true; |
| 928 |
return callback(null); |
| 929 |
} |
| 930 |
else { |
| 931 |
replenish(); |
| 932 |
} |
| 933 |
} |
| 934 |
|
| 935 |
function replenish () { |
| 936 |
while (running < limit && !done) { |
| 937 |
var elem = nextElem(); |
| 938 |
if (elem === null) { |
| 939 |
done = true; |
| 940 |
if (running <= 0) { |
| 941 |
callback(null); |
| 942 |
} |
| 943 |
return; |
| 944 |
} |
| 945 |
running += 1; |
| 946 |
iteratee(elem.value, elem.key, onlyOnce(iterateeCallback)); |
| 947 |
} |
| 948 |
} |
| 949 |
|
| 950 |
replenish(); |
| 951 |
}; |
| 952 |
} |
| 953 |
|
| 954 |
/** |
| 955 |
* The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a |
| 956 |
* time. |
| 957 |
* |
| 958 |
* @name eachOfLimit |
| 959 |
* @static |
| 960 |
* @memberOf module:Collections |
| 961 |
* @method |
| 962 |
* @see [async.eachOf]{@link module:Collections.eachOf} |
| 963 |
* @alias forEachOfLimit |
| 964 |
* @category Collection |
| 965 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 966 |
* @param {number} limit - The maximum number of async operations at a time. |
| 967 |
* @param {AsyncFunction} iteratee - An async function to apply to each |
| 968 |
* item in `coll`. The `key` is the item's key, or index in the case of an |
| 969 |
* array. |
| 970 |
* Invoked with (item, key, callback). |
| 971 |
* @param {Function} [callback] - A callback which is called when all |
| 972 |
* `iteratee` functions have finished, or an error occurs. Invoked with (err). |
| 973 |
*/ |
| 974 |
function eachOfLimit(coll, limit, iteratee, callback) { |
| 975 |
_eachOfLimit(limit)(coll, wrapAsync(iteratee), callback); |
| 976 |
} |
| 977 |
|
| 978 |
function doLimit(fn, limit) { |
| 979 |
return function (iterable, iteratee, callback) { |
| 980 |
return fn(iterable, limit, iteratee, callback); |
| 981 |
}; |
| 982 |
} |
| 983 |
|
| 984 |
// eachOf implementation optimized for array-likes |
| 985 |
function eachOfArrayLike(coll, iteratee, callback) { |
| 986 |
callback = once(callback || noop); |
| 987 |
var index = 0, |
| 988 |
completed = 0, |
| 989 |
length = coll.length; |
| 990 |
if (length === 0) { |
| 991 |
callback(null); |
| 992 |
} |
| 993 |
|
| 994 |
function iteratorCallback(err, value) { |
| 995 |
if (err) { |
| 996 |
callback(err); |
| 997 |
} else if ((++completed === length) || value === breakLoop) { |
| 998 |
callback(null); |
| 999 |
} |
| 1000 |
} |
| 1001 |
|
| 1002 |
for (; index < length; index++) { |
| 1003 |
iteratee(coll[index], index, onlyOnce(iteratorCallback)); |
| 1004 |
} |
| 1005 |
} |
| 1006 |
|
| 1007 |
// a generic version of eachOf which can handle array, object, and iterator cases. |
| 1008 |
var eachOfGeneric = doLimit(eachOfLimit, Infinity); |
| 1009 |
|
| 1010 |
/** |
| 1011 |
* Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument |
| 1012 |
* to the iteratee. |
| 1013 |
* |
| 1014 |
* @name eachOf |
| 1015 |
* @static |
| 1016 |
* @memberOf module:Collections |
| 1017 |
* @method |
| 1018 |
* @alias forEachOf |
| 1019 |
* @category Collection |
| 1020 |
* @see [async.each]{@link module:Collections.each} |
| 1021 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 1022 |
* @param {AsyncFunction} iteratee - A function to apply to each |
| 1023 |
* item in `coll`. |
| 1024 |
* The `key` is the item's key, or index in the case of an array. |
| 1025 |
* Invoked with (item, key, callback). |
| 1026 |
* @param {Function} [callback] - A callback which is called when all |
| 1027 |
* `iteratee` functions have finished, or an error occurs. Invoked with (err). |
| 1028 |
* @example |
| 1029 |
* |
| 1030 |
* var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"}; |
| 1031 |
* var configs = {}; |
| 1032 |
* |
| 1033 |
* async.forEachOf(obj, function (value, key, callback) { |
| 1034 |
* fs.readFile(__dirname + value, "utf8", function (err, data) { |
| 1035 |
* if (err) return callback(err); |
| 1036 |
* try { |
| 1037 |
* configs[key] = JSON.parse(data); |
| 1038 |
* } catch (e) { |
| 1039 |
* return callback(e); |
| 1040 |
* } |
| 1041 |
* callback(); |
| 1042 |
* }); |
| 1043 |
* }, function (err) { |
| 1044 |
* if (err) console.error(err.message); |
| 1045 |
* // configs is now a map of JSON data |
| 1046 |
* doSomethingWith(configs); |
| 1047 |
* }); |
| 1048 |
*/ |
| 1049 |
var eachOf = function(coll, iteratee, callback) { |
| 1050 |
var eachOfImplementation = isArrayLike(coll) ? eachOfArrayLike : eachOfGeneric; |
| 1051 |
eachOfImplementation(coll, wrapAsync(iteratee), callback); |
| 1052 |
}; |
| 1053 |
|
| 1054 |
function doParallel(fn) { |
| 1055 |
return function (obj, iteratee, callback) { |
| 1056 |
return fn(eachOf, obj, wrapAsync(iteratee), callback); |
| 1057 |
}; |
| 1058 |
} |
| 1059 |
|
| 1060 |
function _asyncMap(eachfn, arr, iteratee, callback) { |
| 1061 |
callback = callback || noop; |
| 1062 |
arr = arr || []; |
| 1063 |
var results = []; |
| 1064 |
var counter = 0; |
| 1065 |
var _iteratee = wrapAsync(iteratee); |
| 1066 |
|
| 1067 |
eachfn(arr, function (value, _, callback) { |
| 1068 |
var index = counter++; |
| 1069 |
_iteratee(value, function (err, v) { |
| 1070 |
results[index] = v; |
| 1071 |
callback(err); |
| 1072 |
}); |
| 1073 |
}, function (err) { |
| 1074 |
callback(err, results); |
| 1075 |
}); |
| 1076 |
} |
| 1077 |
|
| 1078 |
/** |
| 1079 |
* Produces a new collection of values by mapping each value in `coll` through |
| 1080 |
* the `iteratee` function. The `iteratee` is called with an item from `coll` |
| 1081 |
* and a callback for when it has finished processing. Each of these callback |
| 1082 |
* takes 2 arguments: an `error`, and the transformed item from `coll`. If |
| 1083 |
* `iteratee` passes an error to its callback, the main `callback` (for the |
| 1084 |
* `map` function) is immediately called with the error. |
| 1085 |
* |
| 1086 |
* Note, that since this function applies the `iteratee` to each item in |
| 1087 |
* parallel, there is no guarantee that the `iteratee` functions will complete |
| 1088 |
* in order. However, the results array will be in the same order as the |
| 1089 |
* original `coll`. |
| 1090 |
* |
| 1091 |
* If `map` is passed an Object, the results will be an Array. The results |
| 1092 |
* will roughly be in the order of the original Objects' keys (but this can |
| 1093 |
* vary across JavaScript engines). |
| 1094 |
* |
| 1095 |
* @name map |
| 1096 |
* @static |
| 1097 |
* @memberOf module:Collections |
| 1098 |
* @method |
| 1099 |
* @category Collection |
| 1100 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 1101 |
* @param {AsyncFunction} iteratee - An async function to apply to each item in |
| 1102 |
* `coll`. |
| 1103 |
* The iteratee should complete with the transformed item. |
| 1104 |
* Invoked with (item, callback). |
| 1105 |
* @param {Function} [callback] - A callback which is called when all `iteratee` |
| 1106 |
* functions have finished, or an error occurs. Results is an Array of the |
| 1107 |
* transformed items from the `coll`. Invoked with (err, results). |
| 1108 |
* @example |
| 1109 |
* |
| 1110 |
* async.map(['file1','file2','file3'], fs.stat, function(err, results) { |
| 1111 |
* // results is now an array of stats for each file |
| 1112 |
* }); |
| 1113 |
*/ |
| 1114 |
var map = doParallel(_asyncMap); |
| 1115 |
|
| 1116 |
/** |
| 1117 |
* Applies the provided arguments to each function in the array, calling |
| 1118 |
* `callback` after all functions have completed. If you only provide the first |
| 1119 |
* argument, `fns`, then it will return a function which lets you pass in the |
| 1120 |
* arguments as if it were a single function call. If more arguments are |
| 1121 |
* provided, `callback` is required while `args` is still optional. |
| 1122 |
* |
| 1123 |
* @name applyEach |
| 1124 |
* @static |
| 1125 |
* @memberOf module:ControlFlow |
| 1126 |
* @method |
| 1127 |
* @category Control Flow |
| 1128 |
* @param {Array|Iterable|Object} fns - A collection of {@link AsyncFunction}s |
| 1129 |
* to all call with the same arguments |
| 1130 |
* @param {...*} [args] - any number of separate arguments to pass to the |
| 1131 |
* function. |
| 1132 |
* @param {Function} [callback] - the final argument should be the callback, |
| 1133 |
* called when all functions have completed processing. |
| 1134 |
* @returns {Function} - If only the first argument, `fns`, is provided, it will |
| 1135 |
* return a function which lets you pass in the arguments as if it were a single |
| 1136 |
* function call. The signature is `(..args, callback)`. If invoked with any |
| 1137 |
* arguments, `callback` is required. |
| 1138 |
* @example |
| 1139 |
* |
| 1140 |
* async.applyEach([enableSearch, updateSchema], 'bucket', callback); |
| 1141 |
* |
| 1142 |
* // partial application example: |
| 1143 |
* async.each( |
| 1144 |
* buckets, |
| 1145 |
* async.applyEach([enableSearch, updateSchema]), |
| 1146 |
* callback |
| 1147 |
* ); |
| 1148 |
*/ |
| 1149 |
var applyEach = applyEach$1(map); |
| 1150 |
|
| 1151 |
function doParallelLimit(fn) { |
| 1152 |
return function (obj, limit, iteratee, callback) { |
| 1153 |
return fn(_eachOfLimit(limit), obj, wrapAsync(iteratee), callback); |
| 1154 |
}; |
| 1155 |
} |
| 1156 |
|
| 1157 |
/** |
| 1158 |
* The same as [`map`]{@link module:Collections.map} but runs a maximum of `limit` async operations at a time. |
| 1159 |
* |
| 1160 |
* @name mapLimit |
| 1161 |
* @static |
| 1162 |
* @memberOf module:Collections |
| 1163 |
* @method |
| 1164 |
* @see [async.map]{@link module:Collections.map} |
| 1165 |
* @category Collection |
| 1166 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 1167 |
* @param {number} limit - The maximum number of async operations at a time. |
| 1168 |
* @param {AsyncFunction} iteratee - An async function to apply to each item in |
| 1169 |
* `coll`. |
| 1170 |
* The iteratee should complete with the transformed item. |
| 1171 |
* Invoked with (item, callback). |
| 1172 |
* @param {Function} [callback] - A callback which is called when all `iteratee` |
| 1173 |
* functions have finished, or an error occurs. Results is an array of the |
| 1174 |
* transformed items from the `coll`. Invoked with (err, results). |
| 1175 |
*/ |
| 1176 |
var mapLimit = doParallelLimit(_asyncMap); |
| 1177 |
|
| 1178 |
/** |
| 1179 |
* The same as [`map`]{@link module:Collections.map} but runs only a single async operation at a time. |
| 1180 |
* |
| 1181 |
* @name mapSeries |
| 1182 |
* @static |
| 1183 |
* @memberOf module:Collections |
| 1184 |
* @method |
| 1185 |
* @see [async.map]{@link module:Collections.map} |
| 1186 |
* @category Collection |
| 1187 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 1188 |
* @param {AsyncFunction} iteratee - An async function to apply to each item in |
| 1189 |
* `coll`. |
| 1190 |
* The iteratee should complete with the transformed item. |
| 1191 |
* Invoked with (item, callback). |
| 1192 |
* @param {Function} [callback] - A callback which is called when all `iteratee` |
| 1193 |
* functions have finished, or an error occurs. Results is an array of the |
| 1194 |
* transformed items from the `coll`. Invoked with (err, results). |
| 1195 |
*/ |
| 1196 |
var mapSeries = doLimit(mapLimit, 1); |
| 1197 |
|
| 1198 |
/** |
| 1199 |
* The same as [`applyEach`]{@link module:ControlFlow.applyEach} but runs only a single async operation at a time. |
| 1200 |
* |
| 1201 |
* @name applyEachSeries |
| 1202 |
* @static |
| 1203 |
* @memberOf module:ControlFlow |
| 1204 |
* @method |
| 1205 |
* @see [async.applyEach]{@link module:ControlFlow.applyEach} |
| 1206 |
* @category Control Flow |
| 1207 |
* @param {Array|Iterable|Object} fns - A collection of {@link AsyncFunction}s to all |
| 1208 |
* call with the same arguments |
| 1209 |
* @param {...*} [args] - any number of separate arguments to pass to the |
| 1210 |
* function. |
| 1211 |
* @param {Function} [callback] - the final argument should be the callback, |
| 1212 |
* called when all functions have completed processing. |
| 1213 |
* @returns {Function} - If only the first argument is provided, it will return |
| 1214 |
* a function which lets you pass in the arguments as if it were a single |
| 1215 |
* function call. |
| 1216 |
*/ |
| 1217 |
var applyEachSeries = applyEach$1(mapSeries); |
| 1218 |
|
| 1219 |
/** |
| 1220 |
* Creates a continuation function with some arguments already applied. |
| 1221 |
* |
| 1222 |
* Useful as a shorthand when combined with other control flow functions. Any |
| 1223 |
* arguments passed to the returned function are added to the arguments |
| 1224 |
* originally passed to apply. |
| 1225 |
* |
| 1226 |
* @name apply |
| 1227 |
* @static |
| 1228 |
* @memberOf module:Utils |
| 1229 |
* @method |
| 1230 |
* @category Util |
| 1231 |
* @param {Function} fn - The function you want to eventually apply all |
| 1232 |
* arguments to. Invokes with (arguments...). |
| 1233 |
* @param {...*} arguments... - Any number of arguments to automatically apply |
| 1234 |
* when the continuation is called. |
| 1235 |
* @returns {Function} the partially-applied function |
| 1236 |
* @example |
| 1237 |
* |
| 1238 |
* // using apply |
| 1239 |
* async.parallel([ |
| 1240 |
* async.apply(fs.writeFile, 'testfile1', 'test1'), |
| 1241 |
* async.apply(fs.writeFile, 'testfile2', 'test2') |
| 1242 |
* ]); |
| 1243 |
* |
| 1244 |
* |
| 1245 |
* // the same process without using apply |
| 1246 |
* async.parallel([ |
| 1247 |
* function(callback) { |
| 1248 |
* fs.writeFile('testfile1', 'test1', callback); |
| 1249 |
* }, |
| 1250 |
* function(callback) { |
| 1251 |
* fs.writeFile('testfile2', 'test2', callback); |
| 1252 |
* } |
| 1253 |
* ]); |
| 1254 |
* |
| 1255 |
* // It's possible to pass any number of additional arguments when calling the |
| 1256 |
* // continuation: |
| 1257 |
* |
| 1258 |
* node> var fn = async.apply(sys.puts, 'one'); |
| 1259 |
* node> fn('two', 'three'); |
| 1260 |
* one |
| 1261 |
* two |
| 1262 |
* three |
| 1263 |
*/ |
| 1264 |
var apply = function(fn/*, ...args*/) { |
| 1265 |
var args = slice(arguments, 1); |
| 1266 |
return function(/*callArgs*/) { |
| 1267 |
var callArgs = slice(arguments); |
| 1268 |
return fn.apply(null, args.concat(callArgs)); |
| 1269 |
}; |
| 1270 |
}; |
| 1271 |
|
| 1272 |
/** |
| 1273 |
* A specialized version of `_.forEach` for arrays without support for |
| 1274 |
* iteratee shorthands. |
| 1275 |
* |
| 1276 |
* @private |
| 1277 |
* @param {Array} [array] The array to iterate over. |
| 1278 |
* @param {Function} iteratee The function invoked per iteration. |
| 1279 |
* @returns {Array} Returns `array`. |
| 1280 |
*/ |
| 1281 |
function arrayEach(array, iteratee) { |
| 1282 |
var index = -1, |
| 1283 |
length = array == null ? 0 : array.length; |
| 1284 |
|
| 1285 |
while (++index < length) { |
| 1286 |
if (iteratee(array[index], index, array) === false) { |
| 1287 |
break; |
| 1288 |
} |
| 1289 |
} |
| 1290 |
return array; |
| 1291 |
} |
| 1292 |
|
| 1293 |
/** |
| 1294 |
* Creates a base function for methods like `_.forIn` and `_.forOwn`. |
| 1295 |
* |
| 1296 |
* @private |
| 1297 |
* @param {boolean} [fromRight] Specify iterating from right to left. |
| 1298 |
* @returns {Function} Returns the new base function. |
| 1299 |
*/ |
| 1300 |
function createBaseFor(fromRight) { |
| 1301 |
return function(object, iteratee, keysFunc) { |
| 1302 |
var index = -1, |
| 1303 |
iterable = Object(object), |
| 1304 |
props = keysFunc(object), |
| 1305 |
length = props.length; |
| 1306 |
|
| 1307 |
while (length--) { |
| 1308 |
var key = props[fromRight ? length : ++index]; |
| 1309 |
if (iteratee(iterable[key], key, iterable) === false) { |
| 1310 |
break; |
| 1311 |
} |
| 1312 |
} |
| 1313 |
return object; |
| 1314 |
}; |
| 1315 |
} |
| 1316 |
|
| 1317 |
/** |
| 1318 |
* The base implementation of `baseForOwn` which iterates over `object` |
| 1319 |
* properties returned by `keysFunc` and invokes `iteratee` for each property. |
| 1320 |
* Iteratee functions may exit iteration early by explicitly returning `false`. |
| 1321 |
* |
| 1322 |
* @private |
| 1323 |
* @param {Object} object The object to iterate over. |
| 1324 |
* @param {Function} iteratee The function invoked per iteration. |
| 1325 |
* @param {Function} keysFunc The function to get the keys of `object`. |
| 1326 |
* @returns {Object} Returns `object`. |
| 1327 |
*/ |
| 1328 |
var baseFor = createBaseFor(); |
| 1329 |
|
| 1330 |
/** |
| 1331 |
* The base implementation of `_.forOwn` without support for iteratee shorthands. |
| 1332 |
* |
| 1333 |
* @private |
| 1334 |
* @param {Object} object The object to iterate over. |
| 1335 |
* @param {Function} iteratee The function invoked per iteration. |
| 1336 |
* @returns {Object} Returns `object`. |
| 1337 |
*/ |
| 1338 |
function baseForOwn(object, iteratee) { |
| 1339 |
return object && baseFor(object, iteratee, keys); |
| 1340 |
} |
| 1341 |
|
| 1342 |
/** |
| 1343 |
* The base implementation of `_.findIndex` and `_.findLastIndex` without |
| 1344 |
* support for iteratee shorthands. |
| 1345 |
* |
| 1346 |
* @private |
| 1347 |
* @param {Array} array The array to inspect. |
| 1348 |
* @param {Function} predicate The function invoked per iteration. |
| 1349 |
* @param {number} fromIndex The index to search from. |
| 1350 |
* @param {boolean} [fromRight] Specify iterating from right to left. |
| 1351 |
* @returns {number} Returns the index of the matched value, else `-1`. |
| 1352 |
*/ |
| 1353 |
function baseFindIndex(array, predicate, fromIndex, fromRight) { |
| 1354 |
var length = array.length, |
| 1355 |
index = fromIndex + (fromRight ? 1 : -1); |
| 1356 |
|
| 1357 |
while ((fromRight ? index-- : ++index < length)) { |
| 1358 |
if (predicate(array[index], index, array)) { |
| 1359 |
return index; |
| 1360 |
} |
| 1361 |
} |
| 1362 |
return -1; |
| 1363 |
} |
| 1364 |
|
| 1365 |
/** |
| 1366 |
* The base implementation of `_.isNaN` without support for number objects. |
| 1367 |
* |
| 1368 |
* @private |
| 1369 |
* @param {*} value The value to check. |
| 1370 |
* @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. |
| 1371 |
*/ |
| 1372 |
function baseIsNaN(value) { |
| 1373 |
return value !== value; |
| 1374 |
} |
| 1375 |
|
| 1376 |
/** |
| 1377 |
* A specialized version of `_.indexOf` which performs strict equality |
| 1378 |
* comparisons of values, i.e. `===`. |
| 1379 |
* |
| 1380 |
* @private |
| 1381 |
* @param {Array} array The array to inspect. |
| 1382 |
* @param {*} value The value to search for. |
| 1383 |
* @param {number} fromIndex The index to search from. |
| 1384 |
* @returns {number} Returns the index of the matched value, else `-1`. |
| 1385 |
*/ |
| 1386 |
function strictIndexOf(array, value, fromIndex) { |
| 1387 |
var index = fromIndex - 1, |
| 1388 |
length = array.length; |
| 1389 |
|
| 1390 |
while (++index < length) { |
| 1391 |
if (array[index] === value) { |
| 1392 |
return index; |
| 1393 |
} |
| 1394 |
} |
| 1395 |
return -1; |
| 1396 |
} |
| 1397 |
|
| 1398 |
/** |
| 1399 |
* The base implementation of `_.indexOf` without `fromIndex` bounds checks. |
| 1400 |
* |
| 1401 |
* @private |
| 1402 |
* @param {Array} array The array to inspect. |
| 1403 |
* @param {*} value The value to search for. |
| 1404 |
* @param {number} fromIndex The index to search from. |
| 1405 |
* @returns {number} Returns the index of the matched value, else `-1`. |
| 1406 |
*/ |
| 1407 |
function baseIndexOf(array, value, fromIndex) { |
| 1408 |
return value === value |
| 1409 |
? strictIndexOf(array, value, fromIndex) |
| 1410 |
: baseFindIndex(array, baseIsNaN, fromIndex); |
| 1411 |
} |
| 1412 |
|
| 1413 |
/** |
| 1414 |
* Determines the best order for running the {@link AsyncFunction}s in `tasks`, based on |
| 1415 |
* their requirements. Each function can optionally depend on other functions |
| 1416 |
* being completed first, and each function is run as soon as its requirements |
| 1417 |
* are satisfied. |
| 1418 |
* |
| 1419 |
* If any of the {@link AsyncFunction}s pass an error to their callback, the `auto` sequence |
| 1420 |
* will stop. Further tasks will not execute (so any other functions depending |
| 1421 |
* on it will not run), and the main `callback` is immediately called with the |
| 1422 |
* error. |
| 1423 |
* |
| 1424 |
* {@link AsyncFunction}s also receive an object containing the results of functions which |
| 1425 |
* have completed so far as the first argument, if they have dependencies. If a |
| 1426 |
* task function has no dependencies, it will only be passed a callback. |
| 1427 |
* |
| 1428 |
* @name auto |
| 1429 |
* @static |
| 1430 |
* @memberOf module:ControlFlow |
| 1431 |
* @method |
| 1432 |
* @category Control Flow |
| 1433 |
* @param {Object} tasks - An object. Each of its properties is either a |
| 1434 |
* function or an array of requirements, with the {@link AsyncFunction} itself the last item |
| 1435 |
* in the array. The object's key of a property serves as the name of the task |
| 1436 |
* defined by that property, i.e. can be used when specifying requirements for |
| 1437 |
* other tasks. The function receives one or two arguments: |
| 1438 |
* * a `results` object, containing the results of the previously executed |
| 1439 |
* functions, only passed if the task has any dependencies, |
| 1440 |
* * a `callback(err, result)` function, which must be called when finished, |
| 1441 |
* passing an `error` (which can be `null`) and the result of the function's |
| 1442 |
* execution. |
| 1443 |
* @param {number} [concurrency=Infinity] - An optional `integer` for |
| 1444 |
* determining the maximum number of tasks that can be run in parallel. By |
| 1445 |
* default, as many as possible. |
| 1446 |
* @param {Function} [callback] - An optional callback which is called when all |
| 1447 |
* the tasks have been completed. It receives the `err` argument if any `tasks` |
| 1448 |
* pass an error to their callback. Results are always returned; however, if an |
| 1449 |
* error occurs, no further `tasks` will be performed, and the results object |
| 1450 |
* will only contain partial results. Invoked with (err, results). |
| 1451 |
* @returns undefined |
| 1452 |
* @example |
| 1453 |
* |
| 1454 |
* async.auto({ |
| 1455 |
* // this function will just be passed a callback |
| 1456 |
* readData: async.apply(fs.readFile, 'data.txt', 'utf-8'), |
| 1457 |
* showData: ['readData', function(results, cb) { |
| 1458 |
* // results.readData is the file's contents |
| 1459 |
* // ... |
| 1460 |
* }] |
| 1461 |
* }, callback); |
| 1462 |
* |
| 1463 |
* async.auto({ |
| 1464 |
* get_data: function(callback) { |
| 1465 |
* console.log('in get_data'); |
| 1466 |
* // async code to get some data |
| 1467 |
* callback(null, 'data', 'converted to array'); |
| 1468 |
* }, |
| 1469 |
* make_folder: function(callback) { |
| 1470 |
* console.log('in make_folder'); |
| 1471 |
* // async code to create a directory to store a file in |
| 1472 |
* // this is run at the same time as getting the data |
| 1473 |
* callback(null, 'folder'); |
| 1474 |
* }, |
| 1475 |
* write_file: ['get_data', 'make_folder', function(results, callback) { |
| 1476 |
* console.log('in write_file', JSON.stringify(results)); |
| 1477 |
* // once there is some data and the directory exists, |
| 1478 |
* // write the data to a file in the directory |
| 1479 |
* callback(null, 'filename'); |
| 1480 |
* }], |
| 1481 |
* email_link: ['write_file', function(results, callback) { |
| 1482 |
* console.log('in email_link', JSON.stringify(results)); |
| 1483 |
* // once the file is written let's email a link to it... |
| 1484 |
* // results.write_file contains the filename returned by write_file. |
| 1485 |
* callback(null, {'file':results.write_file, 'email':'user@example.com'}); |
| 1486 |
* }] |
| 1487 |
* }, function(err, results) { |
| 1488 |
* console.log('err = ', err); |
| 1489 |
* console.log('results = ', results); |
| 1490 |
* }); |
| 1491 |
*/ |
| 1492 |
var auto = function (tasks, concurrency, callback) { |
| 1493 |
if (typeof concurrency === 'function') { |
| 1494 |
// concurrency is optional, shift the args. |
| 1495 |
callback = concurrency; |
| 1496 |
concurrency = null; |
| 1497 |
} |
| 1498 |
callback = callback || noop; |
| 1499 |
var keys$$1 = keys(tasks); |
| 1500 |
var numTasks = keys$$1.length; |
| 1501 |
if (!numTasks) { |
| 1502 |
return callback(null); |
| 1503 |
} |
| 1504 |
if (!concurrency) { |
| 1505 |
concurrency = numTasks; |
| 1506 |
} |
| 1507 |
|
| 1508 |
var results = {}; |
| 1509 |
var runningTasks = 0; |
| 1510 |
var hasError = false; |
| 1511 |
|
| 1512 |
var listeners = Object.create(null); |
| 1513 |
|
| 1514 |
var readyTasks = []; |
| 1515 |
|
| 1516 |
// for cycle detection: |
| 1517 |
var readyToCheck = []; // tasks that have been identified as reachable |
| 1518 |
// without the possibility of returning to an ancestor task |
| 1519 |
var uncheckedDependencies = {}; |
| 1520 |
|
| 1521 |
baseForOwn(tasks, function (task, key) { |
| 1522 |
if (!isArray(task)) { |
| 1523 |
// no dependencies |
| 1524 |
enqueueTask(key, [task]); |
| 1525 |
readyToCheck.push(key); |
| 1526 |
return; |
| 1527 |
} |
| 1528 |
|
| 1529 |
var dependencies = task.slice(0, task.length - 1); |
| 1530 |
var remainingDependencies = dependencies.length; |
| 1531 |
if (remainingDependencies === 0) { |
| 1532 |
enqueueTask(key, task); |
| 1533 |
readyToCheck.push(key); |
| 1534 |
return; |
| 1535 |
} |
| 1536 |
uncheckedDependencies[key] = remainingDependencies; |
| 1537 |
|
| 1538 |
arrayEach(dependencies, function (dependencyName) { |
| 1539 |
if (!tasks[dependencyName]) { |
| 1540 |
throw new Error('async.auto task `' + key + |
| 1541 |
'` has a non-existent dependency `' + |
| 1542 |
dependencyName + '` in ' + |
| 1543 |
dependencies.join(', ')); |
| 1544 |
} |
| 1545 |
addListener(dependencyName, function () { |
| 1546 |
remainingDependencies--; |
| 1547 |
if (remainingDependencies === 0) { |
| 1548 |
enqueueTask(key, task); |
| 1549 |
} |
| 1550 |
}); |
| 1551 |
}); |
| 1552 |
}); |
| 1553 |
|
| 1554 |
checkForDeadlocks(); |
| 1555 |
processQueue(); |
| 1556 |
|
| 1557 |
function enqueueTask(key, task) { |
| 1558 |
readyTasks.push(function () { |
| 1559 |
runTask(key, task); |
| 1560 |
}); |
| 1561 |
} |
| 1562 |
|
| 1563 |
function processQueue() { |
| 1564 |
if (readyTasks.length === 0 && runningTasks === 0) { |
| 1565 |
return callback(null, results); |
| 1566 |
} |
| 1567 |
while(readyTasks.length && runningTasks < concurrency) { |
| 1568 |
var run = readyTasks.shift(); |
| 1569 |
run(); |
| 1570 |
} |
| 1571 |
|
| 1572 |
} |
| 1573 |
|
| 1574 |
function addListener(taskName, fn) { |
| 1575 |
var taskListeners = listeners[taskName]; |
| 1576 |
if (!taskListeners) { |
| 1577 |
taskListeners = listeners[taskName] = []; |
| 1578 |
} |
| 1579 |
|
| 1580 |
taskListeners.push(fn); |
| 1581 |
} |
| 1582 |
|
| 1583 |
function taskComplete(taskName) { |
| 1584 |
var taskListeners = listeners[taskName] || []; |
| 1585 |
arrayEach(taskListeners, function (fn) { |
| 1586 |
fn(); |
| 1587 |
}); |
| 1588 |
processQueue(); |
| 1589 |
} |
| 1590 |
|
| 1591 |
|
| 1592 |
function runTask(key, task) { |
| 1593 |
if (hasError) return; |
| 1594 |
|
| 1595 |
var taskCallback = function(err, result) { |
| 1596 |
runningTasks--; |
| 1597 |
if (arguments.length > 2) { |
| 1598 |
result = slice(arguments, 1); |
| 1599 |
} |
| 1600 |
if (err) { |
| 1601 |
var safeResults = {}; |
| 1602 |
baseForOwn(results, function(val, rkey) { |
| 1603 |
safeResults[rkey] = val; |
| 1604 |
}); |
| 1605 |
safeResults[key] = result; |
| 1606 |
hasError = true; |
| 1607 |
listeners = Object.create(null); |
| 1608 |
|
| 1609 |
callback(err, safeResults); |
| 1610 |
} else { |
| 1611 |
results[key] = result; |
| 1612 |
callback(err, result); |
| 1613 |
taskComplete(key); |
| 1614 |
} |
| 1615 |
}; |
| 1616 |
|
| 1617 |
runningTasks++; |
| 1618 |
var taskFn = wrapAsync(task[task.length - 1]); |
| 1619 |
if (task.length > 1) { |
| 1620 |
taskFn(results, taskCallback); |
| 1621 |
} else { |
| 1622 |
taskFn(taskCallback); |
| 1623 |
} |
| 1624 |
} |
| 1625 |
|
| 1626 |
function checkForDeadlocks() { |
| 1627 |
// Kahn's algorithm |
| 1628 |
// https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm |
| 1629 |
// http://connalle.blogspot.com/2013/10/topological-sortingkahn-algorithm.html |
| 1630 |
var currentTask; |
| 1631 |
var counter = 0; |
| 1632 |
while (readyToCheck.length) { |
| 1633 |
currentTask = readyToCheck.pop(); |
| 1634 |
counter++; |
| 1635 |
arrayEach(getDependents(currentTask), function (dependent) { |
| 1636 |
if (--uncheckedDependencies[dependent] === 0) { |
| 1637 |
readyToCheck.push(dependent); |
| 1638 |
} |
| 1639 |
}); |
| 1640 |
} |
| 1641 |
|
| 1642 |
if (counter !== numTasks) { |
| 1643 |
throw new Error( |
| 1644 |
'async.auto cannot execute tasks due to a recursive dependency' |
| 1645 |
); |
| 1646 |
} |
| 1647 |
} |
| 1648 |
|
| 1649 |
function getDependents(taskName) { |
| 1650 |
var result = []; |
| 1651 |
baseForOwn(tasks, function (task, key) { |
| 1652 |
if (isArray(task) && baseIndexOf(task, taskName, 0) >= 0) { |
| 1653 |
result.push(key); |
| 1654 |
} |
| 1655 |
}); |
| 1656 |
return result; |
| 1657 |
} |
| 1658 |
}; |
| 1659 |
|
| 1660 |
/** |
| 1661 |
* A specialized version of `_.map` for arrays without support for iteratee |
| 1662 |
* shorthands. |
| 1663 |
* |
| 1664 |
* @private |
| 1665 |
* @param {Array} [array] The array to iterate over. |
| 1666 |
* @param {Function} iteratee The function invoked per iteration. |
| 1667 |
* @returns {Array} Returns the new mapped array. |
| 1668 |
*/ |
| 1669 |
function arrayMap(array, iteratee) { |
| 1670 |
var index = -1, |
| 1671 |
length = array == null ? 0 : array.length, |
| 1672 |
result = Array(length); |
| 1673 |
|
| 1674 |
while (++index < length) { |
| 1675 |
result[index] = iteratee(array[index], index, array); |
| 1676 |
} |
| 1677 |
return result; |
| 1678 |
} |
| 1679 |
|
| 1680 |
/** `Object#toString` result references. */ |
| 1681 |
var symbolTag = '[object Symbol]'; |
| 1682 |
|
| 1683 |
/** |
| 1684 |
* Checks if `value` is classified as a `Symbol` primitive or object. |
| 1685 |
* |
| 1686 |
* @static |
| 1687 |
* @memberOf _ |
| 1688 |
* @since 4.0.0 |
| 1689 |
* @category Lang |
| 1690 |
* @param {*} value The value to check. |
| 1691 |
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`. |
| 1692 |
* @example |
| 1693 |
* |
| 1694 |
* _.isSymbol(Symbol.iterator); |
| 1695 |
* // => true |
| 1696 |
* |
| 1697 |
* _.isSymbol('abc'); |
| 1698 |
* // => false |
| 1699 |
*/ |
| 1700 |
function isSymbol(value) { |
| 1701 |
return typeof value == 'symbol' || |
| 1702 |
(isObjectLike(value) && baseGetTag(value) == symbolTag); |
| 1703 |
} |
| 1704 |
|
| 1705 |
/** Used as references for various `Number` constants. */ |
| 1706 |
var INFINITY = 1 / 0; |
| 1707 |
|
| 1708 |
/** Used to convert symbols to primitives and strings. */ |
| 1709 |
var symbolProto = Symbol$1 ? Symbol$1.prototype : undefined; |
| 1710 |
var symbolToString = symbolProto ? symbolProto.toString : undefined; |
| 1711 |
|
| 1712 |
/** |
| 1713 |
* The base implementation of `_.toString` which doesn't convert nullish |
| 1714 |
* values to empty strings. |
| 1715 |
* |
| 1716 |
* @private |
| 1717 |
* @param {*} value The value to process. |
| 1718 |
* @returns {string} Returns the string. |
| 1719 |
*/ |
| 1720 |
function baseToString(value) { |
| 1721 |
// Exit early for strings to avoid a performance hit in some environments. |
| 1722 |
if (typeof value == 'string') { |
| 1723 |
return value; |
| 1724 |
} |
| 1725 |
if (isArray(value)) { |
| 1726 |
// Recursively convert values (susceptible to call stack limits). |
| 1727 |
return arrayMap(value, baseToString) + ''; |
| 1728 |
} |
| 1729 |
if (isSymbol(value)) { |
| 1730 |
return symbolToString ? symbolToString.call(value) : ''; |
| 1731 |
} |
| 1732 |
var result = (value + ''); |
| 1733 |
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; |
| 1734 |
} |
| 1735 |
|
| 1736 |
/** |
| 1737 |
* The base implementation of `_.slice` without an iteratee call guard. |
| 1738 |
* |
| 1739 |
* @private |
| 1740 |
* @param {Array} array The array to slice. |
| 1741 |
* @param {number} [start=0] The start position. |
| 1742 |
* @param {number} [end=array.length] The end position. |
| 1743 |
* @returns {Array} Returns the slice of `array`. |
| 1744 |
*/ |
| 1745 |
function baseSlice(array, start, end) { |
| 1746 |
var index = -1, |
| 1747 |
length = array.length; |
| 1748 |
|
| 1749 |
if (start < 0) { |
| 1750 |
start = -start > length ? 0 : (length + start); |
| 1751 |
} |
| 1752 |
end = end > length ? length : end; |
| 1753 |
if (end < 0) { |
| 1754 |
end += length; |
| 1755 |
} |
| 1756 |
length = start > end ? 0 : ((end - start) >>> 0); |
| 1757 |
start >>>= 0; |
| 1758 |
|
| 1759 |
var result = Array(length); |
| 1760 |
while (++index < length) { |
| 1761 |
result[index] = array[index + start]; |
| 1762 |
} |
| 1763 |
return result; |
| 1764 |
} |
| 1765 |
|
| 1766 |
/** |
| 1767 |
* Casts `array` to a slice if it's needed. |
| 1768 |
* |
| 1769 |
* @private |
| 1770 |
* @param {Array} array The array to inspect. |
| 1771 |
* @param {number} start The start position. |
| 1772 |
* @param {number} [end=array.length] The end position. |
| 1773 |
* @returns {Array} Returns the cast slice. |
| 1774 |
*/ |
| 1775 |
function castSlice(array, start, end) { |
| 1776 |
var length = array.length; |
| 1777 |
end = end === undefined ? length : end; |
| 1778 |
return (!start && end >= length) ? array : baseSlice(array, start, end); |
| 1779 |
} |
| 1780 |
|
| 1781 |
/** |
| 1782 |
* Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol |
| 1783 |
* that is not found in the character symbols. |
| 1784 |
* |
| 1785 |
* @private |
| 1786 |
* @param {Array} strSymbols The string symbols to inspect. |
| 1787 |
* @param {Array} chrSymbols The character symbols to find. |
| 1788 |
* @returns {number} Returns the index of the last unmatched string symbol. |
| 1789 |
*/ |
| 1790 |
function charsEndIndex(strSymbols, chrSymbols) { |
| 1791 |
var index = strSymbols.length; |
| 1792 |
|
| 1793 |
while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} |
| 1794 |
return index; |
| 1795 |
} |
| 1796 |
|
| 1797 |
/** |
| 1798 |
* Used by `_.trim` and `_.trimStart` to get the index of the first string symbol |
| 1799 |
* that is not found in the character symbols. |
| 1800 |
* |
| 1801 |
* @private |
| 1802 |
* @param {Array} strSymbols The string symbols to inspect. |
| 1803 |
* @param {Array} chrSymbols The character symbols to find. |
| 1804 |
* @returns {number} Returns the index of the first unmatched string symbol. |
| 1805 |
*/ |
| 1806 |
function charsStartIndex(strSymbols, chrSymbols) { |
| 1807 |
var index = -1, |
| 1808 |
length = strSymbols.length; |
| 1809 |
|
| 1810 |
while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} |
| 1811 |
return index; |
| 1812 |
} |
| 1813 |
|
| 1814 |
/** |
| 1815 |
* Converts an ASCII `string` to an array. |
| 1816 |
* |
| 1817 |
* @private |
| 1818 |
* @param {string} string The string to convert. |
| 1819 |
* @returns {Array} Returns the converted array. |
| 1820 |
*/ |
| 1821 |
function asciiToArray(string) { |
| 1822 |
return string.split(''); |
| 1823 |
} |
| 1824 |
|
| 1825 |
/** Used to compose unicode character classes. */ |
| 1826 |
var rsAstralRange = '\\ud800-\\udfff'; |
| 1827 |
var rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23'; |
| 1828 |
var rsComboSymbolsRange = '\\u20d0-\\u20f0'; |
| 1829 |
var rsVarRange = '\\ufe0e\\ufe0f'; |
| 1830 |
|
| 1831 |
/** Used to compose unicode capture groups. */ |
| 1832 |
var rsZWJ = '\\u200d'; |
| 1833 |
|
| 1834 |
/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ |
| 1835 |
var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); |
| 1836 |
|
| 1837 |
/** |
| 1838 |
* Checks if `string` contains Unicode symbols. |
| 1839 |
* |
| 1840 |
* @private |
| 1841 |
* @param {string} string The string to inspect. |
| 1842 |
* @returns {boolean} Returns `true` if a symbol is found, else `false`. |
| 1843 |
*/ |
| 1844 |
function hasUnicode(string) { |
| 1845 |
return reHasUnicode.test(string); |
| 1846 |
} |
| 1847 |
|
| 1848 |
/** Used to compose unicode character classes. */ |
| 1849 |
var rsAstralRange$1 = '\\ud800-\\udfff'; |
| 1850 |
var rsComboMarksRange$1 = '\\u0300-\\u036f\\ufe20-\\ufe23'; |
| 1851 |
var rsComboSymbolsRange$1 = '\\u20d0-\\u20f0'; |
| 1852 |
var rsVarRange$1 = '\\ufe0e\\ufe0f'; |
| 1853 |
|
| 1854 |
/** Used to compose unicode capture groups. */ |
| 1855 |
var rsAstral = '[' + rsAstralRange$1 + ']'; |
| 1856 |
var rsCombo = '[' + rsComboMarksRange$1 + rsComboSymbolsRange$1 + ']'; |
| 1857 |
var rsFitz = '\\ud83c[\\udffb-\\udfff]'; |
| 1858 |
var rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')'; |
| 1859 |
var rsNonAstral = '[^' + rsAstralRange$1 + ']'; |
| 1860 |
var rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}'; |
| 1861 |
var rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]'; |
| 1862 |
var rsZWJ$1 = '\\u200d'; |
| 1863 |
|
| 1864 |
/** Used to compose unicode regexes. */ |
| 1865 |
var reOptMod = rsModifier + '?'; |
| 1866 |
var rsOptVar = '[' + rsVarRange$1 + ']?'; |
| 1867 |
var rsOptJoin = '(?:' + rsZWJ$1 + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*'; |
| 1868 |
var rsSeq = rsOptVar + reOptMod + rsOptJoin; |
| 1869 |
var rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; |
| 1870 |
|
| 1871 |
/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ |
| 1872 |
var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); |
| 1873 |
|
| 1874 |
/** |
| 1875 |
* Converts a Unicode `string` to an array. |
| 1876 |
* |
| 1877 |
* @private |
| 1878 |
* @param {string} string The string to convert. |
| 1879 |
* @returns {Array} Returns the converted array. |
| 1880 |
*/ |
| 1881 |
function unicodeToArray(string) { |
| 1882 |
return string.match(reUnicode) || []; |
| 1883 |
} |
| 1884 |
|
| 1885 |
/** |
| 1886 |
* Converts `string` to an array. |
| 1887 |
* |
| 1888 |
* @private |
| 1889 |
* @param {string} string The string to convert. |
| 1890 |
* @returns {Array} Returns the converted array. |
| 1891 |
*/ |
| 1892 |
function stringToArray(string) { |
| 1893 |
return hasUnicode(string) |
| 1894 |
? unicodeToArray(string) |
| 1895 |
: asciiToArray(string); |
| 1896 |
} |
| 1897 |
|
| 1898 |
/** |
| 1899 |
* Converts `value` to a string. An empty string is returned for `null` |
| 1900 |
* and `undefined` values. The sign of `-0` is preserved. |
| 1901 |
* |
| 1902 |
* @static |
| 1903 |
* @memberOf _ |
| 1904 |
* @since 4.0.0 |
| 1905 |
* @category Lang |
| 1906 |
* @param {*} value The value to convert. |
| 1907 |
* @returns {string} Returns the converted string. |
| 1908 |
* @example |
| 1909 |
* |
| 1910 |
* _.toString(null); |
| 1911 |
* // => '' |
| 1912 |
* |
| 1913 |
* _.toString(-0); |
| 1914 |
* // => '-0' |
| 1915 |
* |
| 1916 |
* _.toString([1, 2, 3]); |
| 1917 |
* // => '1,2,3' |
| 1918 |
*/ |
| 1919 |
function toString(value) { |
| 1920 |
return value == null ? '' : baseToString(value); |
| 1921 |
} |
| 1922 |
|
| 1923 |
/** Used to match leading and trailing whitespace. */ |
| 1924 |
var reTrim = /^\s+|\s+$/g; |
| 1925 |
|
| 1926 |
/** |
| 1927 |
* Removes leading and trailing whitespace or specified characters from `string`. |
| 1928 |
* |
| 1929 |
* @static |
| 1930 |
* @memberOf _ |
| 1931 |
* @since 3.0.0 |
| 1932 |
* @category String |
| 1933 |
* @param {string} [string=''] The string to trim. |
| 1934 |
* @param {string} [chars=whitespace] The characters to trim. |
| 1935 |
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. |
| 1936 |
* @returns {string} Returns the trimmed string. |
| 1937 |
* @example |
| 1938 |
* |
| 1939 |
* _.trim(' abc '); |
| 1940 |
* // => 'abc' |
| 1941 |
* |
| 1942 |
* _.trim('-_-abc-_-', '_-'); |
| 1943 |
* // => 'abc' |
| 1944 |
* |
| 1945 |
* _.map([' foo ', ' bar '], _.trim); |
| 1946 |
* // => ['foo', 'bar'] |
| 1947 |
*/ |
| 1948 |
function trim(string, chars, guard) { |
| 1949 |
string = toString(string); |
| 1950 |
if (string && (guard || chars === undefined)) { |
| 1951 |
return string.replace(reTrim, ''); |
| 1952 |
} |
| 1953 |
if (!string || !(chars = baseToString(chars))) { |
| 1954 |
return string; |
| 1955 |
} |
| 1956 |
var strSymbols = stringToArray(string), |
| 1957 |
chrSymbols = stringToArray(chars), |
| 1958 |
start = charsStartIndex(strSymbols, chrSymbols), |
| 1959 |
end = charsEndIndex(strSymbols, chrSymbols) + 1; |
| 1960 |
|
| 1961 |
return castSlice(strSymbols, start, end).join(''); |
| 1962 |
} |
| 1963 |
|
| 1964 |
var FN_ARGS = /^(?:async\s+)?(function)?\s*[^\(]*\(\s*([^\)]*)\)/m; |
| 1965 |
var FN_ARG_SPLIT = /,/; |
| 1966 |
var FN_ARG = /(=.+)?(\s*)$/; |
| 1967 |
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; |
| 1968 |
|
| 1969 |
function parseParams(func) { |
| 1970 |
func = func.toString().replace(STRIP_COMMENTS, ''); |
| 1971 |
func = func.match(FN_ARGS)[2].replace(' ', ''); |
| 1972 |
func = func ? func.split(FN_ARG_SPLIT) : []; |
| 1973 |
func = func.map(function (arg){ |
| 1974 |
return trim(arg.replace(FN_ARG, '')); |
| 1975 |
}); |
| 1976 |
return func; |
| 1977 |
} |
| 1978 |
|
| 1979 |
/** |
| 1980 |
* A dependency-injected version of the [async.auto]{@link module:ControlFlow.auto} function. Dependent |
| 1981 |
* tasks are specified as parameters to the function, after the usual callback |
| 1982 |
* parameter, with the parameter names matching the names of the tasks it |
| 1983 |
* depends on. This can provide even more readable task graphs which can be |
| 1984 |
* easier to maintain. |
| 1985 |
* |
| 1986 |
* If a final callback is specified, the task results are similarly injected, |
| 1987 |
* specified as named parameters after the initial error parameter. |
| 1988 |
* |
| 1989 |
* The autoInject function is purely syntactic sugar and its semantics are |
| 1990 |
* otherwise equivalent to [async.auto]{@link module:ControlFlow.auto}. |
| 1991 |
* |
| 1992 |
* @name autoInject |
| 1993 |
* @static |
| 1994 |
* @memberOf module:ControlFlow |
| 1995 |
* @method |
| 1996 |
* @see [async.auto]{@link module:ControlFlow.auto} |
| 1997 |
* @category Control Flow |
| 1998 |
* @param {Object} tasks - An object, each of whose properties is an {@link AsyncFunction} of |
| 1999 |
* the form 'func([dependencies...], callback). The object's key of a property |
| 2000 |
* serves as the name of the task defined by that property, i.e. can be used |
| 2001 |
* when specifying requirements for other tasks. |
| 2002 |
* * The `callback` parameter is a `callback(err, result)` which must be called |
| 2003 |
* when finished, passing an `error` (which can be `null`) and the result of |
| 2004 |
* the function's execution. The remaining parameters name other tasks on |
| 2005 |
* which the task is dependent, and the results from those tasks are the |
| 2006 |
* arguments of those parameters. |
| 2007 |
* @param {Function} [callback] - An optional callback which is called when all |
| 2008 |
* the tasks have been completed. It receives the `err` argument if any `tasks` |
| 2009 |
* pass an error to their callback, and a `results` object with any completed |
| 2010 |
* task results, similar to `auto`. |
| 2011 |
* @example |
| 2012 |
* |
| 2013 |
* // The example from `auto` can be rewritten as follows: |
| 2014 |
* async.autoInject({ |
| 2015 |
* get_data: function(callback) { |
| 2016 |
* // async code to get some data |
| 2017 |
* callback(null, 'data', 'converted to array'); |
| 2018 |
* }, |
| 2019 |
* make_folder: function(callback) { |
| 2020 |
* // async code to create a directory to store a file in |
| 2021 |
* // this is run at the same time as getting the data |
| 2022 |
* callback(null, 'folder'); |
| 2023 |
* }, |
| 2024 |
* write_file: function(get_data, make_folder, callback) { |
| 2025 |
* // once there is some data and the directory exists, |
| 2026 |
* // write the data to a file in the directory |
| 2027 |
* callback(null, 'filename'); |
| 2028 |
* }, |
| 2029 |
* email_link: function(write_file, callback) { |
| 2030 |
* // once the file is written let's email a link to it... |
| 2031 |
* // write_file contains the filename returned by write_file. |
| 2032 |
* callback(null, {'file':write_file, 'email':'user@example.com'}); |
| 2033 |
* } |
| 2034 |
* }, function(err, results) { |
| 2035 |
* console.log('err = ', err); |
| 2036 |
* console.log('email_link = ', results.email_link); |
| 2037 |
* }); |
| 2038 |
* |
| 2039 |
* // If you are using a JS minifier that mangles parameter names, `autoInject` |
| 2040 |
* // will not work with plain functions, since the parameter names will be |
| 2041 |
* // collapsed to a single letter identifier. To work around this, you can |
| 2042 |
* // explicitly specify the names of the parameters your task function needs |
| 2043 |
* // in an array, similar to Angular.js dependency injection. |
| 2044 |
* |
| 2045 |
* // This still has an advantage over plain `auto`, since the results a task |
| 2046 |
* // depends on are still spread into arguments. |
| 2047 |
* async.autoInject({ |
| 2048 |
* //... |
| 2049 |
* write_file: ['get_data', 'make_folder', function(get_data, make_folder, callback) { |
| 2050 |
* callback(null, 'filename'); |
| 2051 |
* }], |
| 2052 |
* email_link: ['write_file', function(write_file, callback) { |
| 2053 |
* callback(null, {'file':write_file, 'email':'user@example.com'}); |
| 2054 |
* }] |
| 2055 |
* //... |
| 2056 |
* }, function(err, results) { |
| 2057 |
* console.log('err = ', err); |
| 2058 |
* console.log('email_link = ', results.email_link); |
| 2059 |
* }); |
| 2060 |
*/ |
| 2061 |
function autoInject(tasks, callback) { |
| 2062 |
var newTasks = {}; |
| 2063 |
|
| 2064 |
baseForOwn(tasks, function (taskFn, key) { |
| 2065 |
var params; |
| 2066 |
var fnIsAsync = isAsync(taskFn); |
| 2067 |
var hasNoDeps = |
| 2068 |
(!fnIsAsync && taskFn.length === 1) || |
| 2069 |
(fnIsAsync && taskFn.length === 0); |
| 2070 |
|
| 2071 |
if (isArray(taskFn)) { |
| 2072 |
params = taskFn.slice(0, -1); |
| 2073 |
taskFn = taskFn[taskFn.length - 1]; |
| 2074 |
|
| 2075 |
newTasks[key] = params.concat(params.length > 0 ? newTask : taskFn); |
| 2076 |
} else if (hasNoDeps) { |
| 2077 |
// no dependencies, use the function as-is |
| 2078 |
newTasks[key] = taskFn; |
| 2079 |
} else { |
| 2080 |
params = parseParams(taskFn); |
| 2081 |
if (taskFn.length === 0 && !fnIsAsync && params.length === 0) { |
| 2082 |
throw new Error("autoInject task functions require explicit parameters."); |
| 2083 |
} |
| 2084 |
|
| 2085 |
// remove callback param |
| 2086 |
if (!fnIsAsync) params.pop(); |
| 2087 |
|
| 2088 |
newTasks[key] = params.concat(newTask); |
| 2089 |
} |
| 2090 |
|
| 2091 |
function newTask(results, taskCb) { |
| 2092 |
var newArgs = arrayMap(params, function (name) { |
| 2093 |
return results[name]; |
| 2094 |
}); |
| 2095 |
newArgs.push(taskCb); |
| 2096 |
wrapAsync(taskFn).apply(null, newArgs); |
| 2097 |
} |
| 2098 |
}); |
| 2099 |
|
| 2100 |
auto(newTasks, callback); |
| 2101 |
} |
| 2102 |
|
| 2103 |
// Simple doubly linked list (https://en.wikipedia.org/wiki/Doubly_linked_list) implementation |
| 2104 |
// used for queues. This implementation assumes that the node provided by the user can be modified |
| 2105 |
// to adjust the next and last properties. We implement only the minimal functionality |
| 2106 |
// for queue support. |
| 2107 |
function DLL() { |
| 2108 |
this.head = this.tail = null; |
| 2109 |
this.length = 0; |
| 2110 |
} |
| 2111 |
|
| 2112 |
function setInitial(dll, node) { |
| 2113 |
dll.length = 1; |
| 2114 |
dll.head = dll.tail = node; |
| 2115 |
} |
| 2116 |
|
| 2117 |
DLL.prototype.removeLink = function(node) { |
| 2118 |
if (node.prev) node.prev.next = node.next; |
| 2119 |
else this.head = node.next; |
| 2120 |
if (node.next) node.next.prev = node.prev; |
| 2121 |
else this.tail = node.prev; |
| 2122 |
|
| 2123 |
node.prev = node.next = null; |
| 2124 |
this.length -= 1; |
| 2125 |
return node; |
| 2126 |
}; |
| 2127 |
|
| 2128 |
DLL.prototype.empty = function () { |
| 2129 |
while(this.head) this.shift(); |
| 2130 |
return this; |
| 2131 |
}; |
| 2132 |
|
| 2133 |
DLL.prototype.insertAfter = function(node, newNode) { |
| 2134 |
newNode.prev = node; |
| 2135 |
newNode.next = node.next; |
| 2136 |
if (node.next) node.next.prev = newNode; |
| 2137 |
else this.tail = newNode; |
| 2138 |
node.next = newNode; |
| 2139 |
this.length += 1; |
| 2140 |
}; |
| 2141 |
|
| 2142 |
DLL.prototype.insertBefore = function(node, newNode) { |
| 2143 |
newNode.prev = node.prev; |
| 2144 |
newNode.next = node; |
| 2145 |
if (node.prev) node.prev.next = newNode; |
| 2146 |
else this.head = newNode; |
| 2147 |
node.prev = newNode; |
| 2148 |
this.length += 1; |
| 2149 |
}; |
| 2150 |
|
| 2151 |
DLL.prototype.unshift = function(node) { |
| 2152 |
if (this.head) this.insertBefore(this.head, node); |
| 2153 |
else setInitial(this, node); |
| 2154 |
}; |
| 2155 |
|
| 2156 |
DLL.prototype.push = function(node) { |
| 2157 |
if (this.tail) this.insertAfter(this.tail, node); |
| 2158 |
else setInitial(this, node); |
| 2159 |
}; |
| 2160 |
|
| 2161 |
DLL.prototype.shift = function() { |
| 2162 |
return this.head && this.removeLink(this.head); |
| 2163 |
}; |
| 2164 |
|
| 2165 |
DLL.prototype.pop = function() { |
| 2166 |
return this.tail && this.removeLink(this.tail); |
| 2167 |
}; |
| 2168 |
|
| 2169 |
DLL.prototype.toArray = function () { |
| 2170 |
var arr = Array(this.length); |
| 2171 |
var curr = this.head; |
| 2172 |
for(var idx = 0; idx < this.length; idx++) { |
| 2173 |
arr[idx] = curr.data; |
| 2174 |
curr = curr.next; |
| 2175 |
} |
| 2176 |
return arr; |
| 2177 |
}; |
| 2178 |
|
| 2179 |
DLL.prototype.remove = function (testFn) { |
| 2180 |
var curr = this.head; |
| 2181 |
while(!!curr) { |
| 2182 |
var next = curr.next; |
| 2183 |
if (testFn(curr)) { |
| 2184 |
this.removeLink(curr); |
| 2185 |
} |
| 2186 |
curr = next; |
| 2187 |
} |
| 2188 |
return this; |
| 2189 |
}; |
| 2190 |
|
| 2191 |
function queue(worker, concurrency, payload) { |
| 2192 |
if (concurrency == null) { |
| 2193 |
concurrency = 1; |
| 2194 |
} |
| 2195 |
else if(concurrency === 0) { |
| 2196 |
throw new Error('Concurrency must not be zero'); |
| 2197 |
} |
| 2198 |
|
| 2199 |
var _worker = wrapAsync(worker); |
| 2200 |
var numRunning = 0; |
| 2201 |
var workersList = []; |
| 2202 |
|
| 2203 |
function _insert(data, insertAtFront, callback) { |
| 2204 |
if (callback != null && typeof callback !== 'function') { |
| 2205 |
throw new Error('task callback must be a function'); |
| 2206 |
} |
| 2207 |
q.started = true; |
| 2208 |
if (!isArray(data)) { |
| 2209 |
data = [data]; |
| 2210 |
} |
| 2211 |
if (data.length === 0 && q.idle()) { |
| 2212 |
// call drain immediately if there are no tasks |
| 2213 |
return setImmediate$1(function() { |
| 2214 |
q.drain(); |
| 2215 |
}); |
| 2216 |
} |
| 2217 |
|
| 2218 |
for (var i = 0, l = data.length; i < l; i++) { |
| 2219 |
var item = { |
| 2220 |
data: data[i], |
| 2221 |
callback: callback || noop |
| 2222 |
}; |
| 2223 |
|
| 2224 |
if (insertAtFront) { |
| 2225 |
q._tasks.unshift(item); |
| 2226 |
} else { |
| 2227 |
q._tasks.push(item); |
| 2228 |
} |
| 2229 |
} |
| 2230 |
setImmediate$1(q.process); |
| 2231 |
} |
| 2232 |
|
| 2233 |
function _next(tasks) { |
| 2234 |
return function(err){ |
| 2235 |
numRunning -= 1; |
| 2236 |
|
| 2237 |
for (var i = 0, l = tasks.length; i < l; i++) { |
| 2238 |
var task = tasks[i]; |
| 2239 |
var index = baseIndexOf(workersList, task, 0); |
| 2240 |
if (index >= 0) { |
| 2241 |
workersList.splice(index); |
| 2242 |
} |
| 2243 |
|
| 2244 |
task.callback.apply(task, arguments); |
| 2245 |
|
| 2246 |
if (err != null) { |
| 2247 |
q.error(err, task.data); |
| 2248 |
} |
| 2249 |
} |
| 2250 |
|
| 2251 |
if (numRunning <= (q.concurrency - q.buffer) ) { |
| 2252 |
q.unsaturated(); |
| 2253 |
} |
| 2254 |
|
| 2255 |
if (q.idle()) { |
| 2256 |
q.drain(); |
| 2257 |
} |
| 2258 |
q.process(); |
| 2259 |
}; |
| 2260 |
} |
| 2261 |
|
| 2262 |
var isProcessing = false; |
| 2263 |
var q = { |
| 2264 |
_tasks: new DLL(), |
| 2265 |
concurrency: concurrency, |
| 2266 |
payload: payload, |
| 2267 |
saturated: noop, |
| 2268 |
unsaturated:noop, |
| 2269 |
buffer: concurrency / 4, |
| 2270 |
empty: noop, |
| 2271 |
drain: noop, |
| 2272 |
error: noop, |
| 2273 |
started: false, |
| 2274 |
paused: false, |
| 2275 |
push: function (data, callback) { |
| 2276 |
_insert(data, false, callback); |
| 2277 |
}, |
| 2278 |
kill: function () { |
| 2279 |
q.drain = noop; |
| 2280 |
q._tasks.empty(); |
| 2281 |
}, |
| 2282 |
unshift: function (data, callback) { |
| 2283 |
_insert(data, true, callback); |
| 2284 |
}, |
| 2285 |
remove: function (testFn) { |
| 2286 |
q._tasks.remove(testFn); |
| 2287 |
}, |
| 2288 |
process: function () { |
| 2289 |
// Avoid trying to start too many processing operations. This can occur |
| 2290 |
// when callbacks resolve synchronously (#1267). |
| 2291 |
if (isProcessing) { |
| 2292 |
return; |
| 2293 |
} |
| 2294 |
isProcessing = true; |
| 2295 |
while(!q.paused && numRunning < q.concurrency && q._tasks.length){ |
| 2296 |
var tasks = [], data = []; |
| 2297 |
var l = q._tasks.length; |
| 2298 |
if (q.payload) l = Math.min(l, q.payload); |
| 2299 |
for (var i = 0; i < l; i++) { |
| 2300 |
var node = q._tasks.shift(); |
| 2301 |
tasks.push(node); |
| 2302 |
data.push(node.data); |
| 2303 |
} |
| 2304 |
|
| 2305 |
numRunning += 1; |
| 2306 |
workersList.push(tasks[0]); |
| 2307 |
|
| 2308 |
if (q._tasks.length === 0) { |
| 2309 |
q.empty(); |
| 2310 |
} |
| 2311 |
|
| 2312 |
if (numRunning === q.concurrency) { |
| 2313 |
q.saturated(); |
| 2314 |
} |
| 2315 |
|
| 2316 |
var cb = onlyOnce(_next(tasks)); |
| 2317 |
_worker(data, cb); |
| 2318 |
} |
| 2319 |
isProcessing = false; |
| 2320 |
}, |
| 2321 |
length: function () { |
| 2322 |
return q._tasks.length; |
| 2323 |
}, |
| 2324 |
running: function () { |
| 2325 |
return numRunning; |
| 2326 |
}, |
| 2327 |
workersList: function () { |
| 2328 |
return workersList; |
| 2329 |
}, |
| 2330 |
idle: function() { |
| 2331 |
return q._tasks.length + numRunning === 0; |
| 2332 |
}, |
| 2333 |
pause: function () { |
| 2334 |
q.paused = true; |
| 2335 |
}, |
| 2336 |
resume: function () { |
| 2337 |
if (q.paused === false) { return; } |
| 2338 |
q.paused = false; |
| 2339 |
setImmediate$1(q.process); |
| 2340 |
} |
| 2341 |
}; |
| 2342 |
return q; |
| 2343 |
} |
| 2344 |
|
| 2345 |
/** |
| 2346 |
* A cargo of tasks for the worker function to complete. Cargo inherits all of |
| 2347 |
* the same methods and event callbacks as [`queue`]{@link module:ControlFlow.queue}. |
| 2348 |
* @typedef {Object} CargoObject |
| 2349 |
* @memberOf module:ControlFlow |
| 2350 |
* @property {Function} length - A function returning the number of items |
| 2351 |
* waiting to be processed. Invoke like `cargo.length()`. |
| 2352 |
* @property {number} payload - An `integer` for determining how many tasks |
| 2353 |
* should be process per round. This property can be changed after a `cargo` is |
| 2354 |
* created to alter the payload on-the-fly. |
| 2355 |
* @property {Function} push - Adds `task` to the `queue`. The callback is |
| 2356 |
* called once the `worker` has finished processing the task. Instead of a |
| 2357 |
* single task, an array of `tasks` can be submitted. The respective callback is |
| 2358 |
* used for every task in the list. Invoke like `cargo.push(task, [callback])`. |
| 2359 |
* @property {Function} saturated - A callback that is called when the |
| 2360 |
* `queue.length()` hits the concurrency and further tasks will be queued. |
| 2361 |
* @property {Function} empty - A callback that is called when the last item |
| 2362 |
* from the `queue` is given to a `worker`. |
| 2363 |
* @property {Function} drain - A callback that is called when the last item |
| 2364 |
* from the `queue` has returned from the `worker`. |
| 2365 |
* @property {Function} idle - a function returning false if there are items |
| 2366 |
* waiting or being processed, or true if not. Invoke like `cargo.idle()`. |
| 2367 |
* @property {Function} pause - a function that pauses the processing of tasks |
| 2368 |
* until `resume()` is called. Invoke like `cargo.pause()`. |
| 2369 |
* @property {Function} resume - a function that resumes the processing of |
| 2370 |
* queued tasks when the queue is paused. Invoke like `cargo.resume()`. |
| 2371 |
* @property {Function} kill - a function that removes the `drain` callback and |
| 2372 |
* empties remaining tasks from the queue forcing it to go idle. Invoke like `cargo.kill()`. |
| 2373 |
*/ |
| 2374 |
|
| 2375 |
/** |
| 2376 |
* Creates a `cargo` object with the specified payload. Tasks added to the |
| 2377 |
* cargo will be processed altogether (up to the `payload` limit). If the |
| 2378 |
* `worker` is in progress, the task is queued until it becomes available. Once |
| 2379 |
* the `worker` has completed some tasks, each callback of those tasks is |
| 2380 |
* called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966) |
| 2381 |
* for how `cargo` and `queue` work. |
| 2382 |
* |
| 2383 |
* While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers |
| 2384 |
* at a time, cargo passes an array of tasks to a single worker, repeating |
| 2385 |
* when the worker is finished. |
| 2386 |
* |
| 2387 |
* @name cargo |
| 2388 |
* @static |
| 2389 |
* @memberOf module:ControlFlow |
| 2390 |
* @method |
| 2391 |
* @see [async.queue]{@link module:ControlFlow.queue} |
| 2392 |
* @category Control Flow |
| 2393 |
* @param {AsyncFunction} worker - An asynchronous function for processing an array |
| 2394 |
* of queued tasks. Invoked with `(tasks, callback)`. |
| 2395 |
* @param {number} [payload=Infinity] - An optional `integer` for determining |
| 2396 |
* how many tasks should be processed per round; if omitted, the default is |
| 2397 |
* unlimited. |
| 2398 |
* @returns {module:ControlFlow.CargoObject} A cargo object to manage the tasks. Callbacks can |
| 2399 |
* attached as certain properties to listen for specific events during the |
| 2400 |
* lifecycle of the cargo and inner queue. |
| 2401 |
* @example |
| 2402 |
* |
| 2403 |
* // create a cargo object with payload 2 |
| 2404 |
* var cargo = async.cargo(function(tasks, callback) { |
| 2405 |
* for (var i=0; i<tasks.length; i++) { |
| 2406 |
* console.log('hello ' + tasks[i].name); |
| 2407 |
* } |
| 2408 |
* callback(); |
| 2409 |
* }, 2); |
| 2410 |
* |
| 2411 |
* // add some items |
| 2412 |
* cargo.push({name: 'foo'}, function(err) { |
| 2413 |
* console.log('finished processing foo'); |
| 2414 |
* }); |
| 2415 |
* cargo.push({name: 'bar'}, function(err) { |
| 2416 |
* console.log('finished processing bar'); |
| 2417 |
* }); |
| 2418 |
* cargo.push({name: 'baz'}, function(err) { |
| 2419 |
* console.log('finished processing baz'); |
| 2420 |
* }); |
| 2421 |
*/ |
| 2422 |
function cargo(worker, payload) { |
| 2423 |
return queue(worker, 1, payload); |
| 2424 |
} |
| 2425 |
|
| 2426 |
/** |
| 2427 |
* The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time. |
| 2428 |
* |
| 2429 |
* @name eachOfSeries |
| 2430 |
* @static |
| 2431 |
* @memberOf module:Collections |
| 2432 |
* @method |
| 2433 |
* @see [async.eachOf]{@link module:Collections.eachOf} |
| 2434 |
* @alias forEachOfSeries |
| 2435 |
* @category Collection |
| 2436 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 2437 |
* @param {AsyncFunction} iteratee - An async function to apply to each item in |
| 2438 |
* `coll`. |
| 2439 |
* Invoked with (item, key, callback). |
| 2440 |
* @param {Function} [callback] - A callback which is called when all `iteratee` |
| 2441 |
* functions have finished, or an error occurs. Invoked with (err). |
| 2442 |
*/ |
| 2443 |
var eachOfSeries = doLimit(eachOfLimit, 1); |
| 2444 |
|
| 2445 |
/** |
| 2446 |
* Reduces `coll` into a single value using an async `iteratee` to return each |
| 2447 |
* successive step. `memo` is the initial state of the reduction. This function |
| 2448 |
* only operates in series. |
| 2449 |
* |
| 2450 |
* For performance reasons, it may make sense to split a call to this function |
| 2451 |
* into a parallel map, and then use the normal `Array.prototype.reduce` on the |
| 2452 |
* results. This function is for situations where each step in the reduction |
| 2453 |
* needs to be async; if you can get the data before reducing it, then it's |
| 2454 |
* probably a good idea to do so. |
| 2455 |
* |
| 2456 |
* @name reduce |
| 2457 |
* @static |
| 2458 |
* @memberOf module:Collections |
| 2459 |
* @method |
| 2460 |
* @alias inject |
| 2461 |
* @alias foldl |
| 2462 |
* @category Collection |
| 2463 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 2464 |
* @param {*} memo - The initial state of the reduction. |
| 2465 |
* @param {AsyncFunction} iteratee - A function applied to each item in the |
| 2466 |
* array to produce the next step in the reduction. |
| 2467 |
* The `iteratee` should complete with the next state of the reduction. |
| 2468 |
* If the iteratee complete with an error, the reduction is stopped and the |
| 2469 |
* main `callback` is immediately called with the error. |
| 2470 |
* Invoked with (memo, item, callback). |
| 2471 |
* @param {Function} [callback] - A callback which is called after all the |
| 2472 |
* `iteratee` functions have finished. Result is the reduced value. Invoked with |
| 2473 |
* (err, result). |
| 2474 |
* @example |
| 2475 |
* |
| 2476 |
* async.reduce([1,2,3], 0, function(memo, item, callback) { |
| 2477 |
* // pointless async: |
| 2478 |
* process.nextTick(function() { |
| 2479 |
* callback(null, memo + item) |
| 2480 |
* }); |
| 2481 |
* }, function(err, result) { |
| 2482 |
* // result is now equal to the last value of memo, which is 6 |
| 2483 |
* }); |
| 2484 |
*/ |
| 2485 |
function reduce(coll, memo, iteratee, callback) { |
| 2486 |
callback = once(callback || noop); |
| 2487 |
var _iteratee = wrapAsync(iteratee); |
| 2488 |
eachOfSeries(coll, function(x, i, callback) { |
| 2489 |
_iteratee(memo, x, function(err, v) { |
| 2490 |
memo = v; |
| 2491 |
callback(err); |
| 2492 |
}); |
| 2493 |
}, function(err) { |
| 2494 |
callback(err, memo); |
| 2495 |
}); |
| 2496 |
} |
| 2497 |
|
| 2498 |
/** |
| 2499 |
* Version of the compose function that is more natural to read. Each function |
| 2500 |
* consumes the return value of the previous function. It is the equivalent of |
| 2501 |
* [compose]{@link module:ControlFlow.compose} with the arguments reversed. |
| 2502 |
* |
| 2503 |
* Each function is executed with the `this` binding of the composed function. |
| 2504 |
* |
| 2505 |
* @name seq |
| 2506 |
* @static |
| 2507 |
* @memberOf module:ControlFlow |
| 2508 |
* @method |
| 2509 |
* @see [async.compose]{@link module:ControlFlow.compose} |
| 2510 |
* @category Control Flow |
| 2511 |
* @param {...AsyncFunction} functions - the asynchronous functions to compose |
| 2512 |
* @returns {Function} a function that composes the `functions` in order |
| 2513 |
* @example |
| 2514 |
* |
| 2515 |
* // Requires lodash (or underscore), express3 and dresende's orm2. |
| 2516 |
* // Part of an app, that fetches cats of the logged user. |
| 2517 |
* // This example uses `seq` function to avoid overnesting and error |
| 2518 |
* // handling clutter. |
| 2519 |
* app.get('/cats', function(request, response) { |
| 2520 |
* var User = request.models.User; |
| 2521 |
* async.seq( |
| 2522 |
* _.bind(User.get, User), // 'User.get' has signature (id, callback(err, data)) |
| 2523 |
* function(user, fn) { |
| 2524 |
* user.getCats(fn); // 'getCats' has signature (callback(err, data)) |
| 2525 |
* } |
| 2526 |
* )(req.session.user_id, function (err, cats) { |
| 2527 |
* if (err) { |
| 2528 |
* console.error(err); |
| 2529 |
* response.json({ status: 'error', message: err.message }); |
| 2530 |
* } else { |
| 2531 |
* response.json({ status: 'ok', message: 'Cats found', data: cats }); |
| 2532 |
* } |
| 2533 |
* }); |
| 2534 |
* }); |
| 2535 |
*/ |
| 2536 |
function seq(/*...functions*/) { |
| 2537 |
var _functions = arrayMap(arguments, wrapAsync); |
| 2538 |
return function(/*...args*/) { |
| 2539 |
var args = slice(arguments); |
| 2540 |
var that = this; |
| 2541 |
|
| 2542 |
var cb = args[args.length - 1]; |
| 2543 |
if (typeof cb == 'function') { |
| 2544 |
args.pop(); |
| 2545 |
} else { |
| 2546 |
cb = noop; |
| 2547 |
} |
| 2548 |
|
| 2549 |
reduce(_functions, args, function(newargs, fn, cb) { |
| 2550 |
fn.apply(that, newargs.concat(function(err/*, ...nextargs*/) { |
| 2551 |
var nextargs = slice(arguments, 1); |
| 2552 |
cb(err, nextargs); |
| 2553 |
})); |
| 2554 |
}, |
| 2555 |
function(err, results) { |
| 2556 |
cb.apply(that, [err].concat(results)); |
| 2557 |
}); |
| 2558 |
}; |
| 2559 |
} |
| 2560 |
|
| 2561 |
/** |
| 2562 |
* Creates a function which is a composition of the passed asynchronous |
| 2563 |
* functions. Each function consumes the return value of the function that |
| 2564 |
* follows. Composing functions `f()`, `g()`, and `h()` would produce the result |
| 2565 |
* of `f(g(h()))`, only this version uses callbacks to obtain the return values. |
| 2566 |
* |
| 2567 |
* Each function is executed with the `this` binding of the composed function. |
| 2568 |
* |
| 2569 |
* @name compose |
| 2570 |
* @static |
| 2571 |
* @memberOf module:ControlFlow |
| 2572 |
* @method |
| 2573 |
* @category Control Flow |
| 2574 |
* @param {...AsyncFunction} functions - the asynchronous functions to compose |
| 2575 |
* @returns {Function} an asynchronous function that is the composed |
| 2576 |
* asynchronous `functions` |
| 2577 |
* @example |
| 2578 |
* |
| 2579 |
* function add1(n, callback) { |
| 2580 |
* setTimeout(function () { |
| 2581 |
* callback(null, n + 1); |
| 2582 |
* }, 10); |
| 2583 |
* } |
| 2584 |
* |
| 2585 |
* function mul3(n, callback) { |
| 2586 |
* setTimeout(function () { |
| 2587 |
* callback(null, n * 3); |
| 2588 |
* }, 10); |
| 2589 |
* } |
| 2590 |
* |
| 2591 |
* var add1mul3 = async.compose(mul3, add1); |
| 2592 |
* add1mul3(4, function (err, result) { |
| 2593 |
* // result now equals 15 |
| 2594 |
* }); |
| 2595 |
*/ |
| 2596 |
var compose = function(/*...args*/) { |
| 2597 |
return seq.apply(null, slice(arguments).reverse()); |
| 2598 |
}; |
| 2599 |
|
| 2600 |
function concat$1(eachfn, arr, fn, callback) { |
| 2601 |
var result = []; |
| 2602 |
eachfn(arr, function (x, index, cb) { |
| 2603 |
fn(x, function (err, y) { |
| 2604 |
result = result.concat(y || []); |
| 2605 |
cb(err); |
| 2606 |
}); |
| 2607 |
}, function (err) { |
| 2608 |
callback(err, result); |
| 2609 |
}); |
| 2610 |
} |
| 2611 |
|
| 2612 |
/** |
| 2613 |
* Applies `iteratee` to each item in `coll`, concatenating the results. Returns |
| 2614 |
* the concatenated list. The `iteratee`s are called in parallel, and the |
| 2615 |
* results are concatenated as they return. There is no guarantee that the |
| 2616 |
* results array will be returned in the original order of `coll` passed to the |
| 2617 |
* `iteratee` function. |
| 2618 |
* |
| 2619 |
* @name concat |
| 2620 |
* @static |
| 2621 |
* @memberOf module:Collections |
| 2622 |
* @method |
| 2623 |
* @category Collection |
| 2624 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 2625 |
* @param {AsyncFunction} iteratee - A function to apply to each item in `coll`, |
| 2626 |
* which should use an array as its result. Invoked with (item, callback). |
| 2627 |
* @param {Function} [callback(err)] - A callback which is called after all the |
| 2628 |
* `iteratee` functions have finished, or an error occurs. Results is an array |
| 2629 |
* containing the concatenated results of the `iteratee` function. Invoked with |
| 2630 |
* (err, results). |
| 2631 |
* @example |
| 2632 |
* |
| 2633 |
* async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files) { |
| 2634 |
* // files is now a list of filenames that exist in the 3 directories |
| 2635 |
* }); |
| 2636 |
*/ |
| 2637 |
var concat = doParallel(concat$1); |
| 2638 |
|
| 2639 |
function doSeries(fn) { |
| 2640 |
return function (obj, iteratee, callback) { |
| 2641 |
return fn(eachOfSeries, obj, wrapAsync(iteratee), callback); |
| 2642 |
}; |
| 2643 |
} |
| 2644 |
|
| 2645 |
/** |
| 2646 |
* The same as [`concat`]{@link module:Collections.concat} but runs only a single async operation at a time. |
| 2647 |
* |
| 2648 |
* @name concatSeries |
| 2649 |
* @static |
| 2650 |
* @memberOf module:Collections |
| 2651 |
* @method |
| 2652 |
* @see [async.concat]{@link module:Collections.concat} |
| 2653 |
* @category Collection |
| 2654 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 2655 |
* @param {AsyncFunction} iteratee - A function to apply to each item in `coll`. |
| 2656 |
* The iteratee should complete with an array an array of results. |
| 2657 |
* Invoked with (item, callback). |
| 2658 |
* @param {Function} [callback(err)] - A callback which is called after all the |
| 2659 |
* `iteratee` functions have finished, or an error occurs. Results is an array |
| 2660 |
* containing the concatenated results of the `iteratee` function. Invoked with |
| 2661 |
* (err, results). |
| 2662 |
*/ |
| 2663 |
var concatSeries = doSeries(concat$1); |
| 2664 |
|
| 2665 |
/** |
| 2666 |
* Returns a function that when called, calls-back with the values provided. |
| 2667 |
* Useful as the first function in a [`waterfall`]{@link module:ControlFlow.waterfall}, or for plugging values in to |
| 2668 |
* [`auto`]{@link module:ControlFlow.auto}. |
| 2669 |
* |
| 2670 |
* @name constant |
| 2671 |
* @static |
| 2672 |
* @memberOf module:Utils |
| 2673 |
* @method |
| 2674 |
* @category Util |
| 2675 |
* @param {...*} arguments... - Any number of arguments to automatically invoke |
| 2676 |
* callback with. |
| 2677 |
* @returns {AsyncFunction} Returns a function that when invoked, automatically |
| 2678 |
* invokes the callback with the previous given arguments. |
| 2679 |
* @example |
| 2680 |
* |
| 2681 |
* async.waterfall([ |
| 2682 |
* async.constant(42), |
| 2683 |
* function (value, next) { |
| 2684 |
* // value === 42 |
| 2685 |
* }, |
| 2686 |
* //... |
| 2687 |
* ], callback); |
| 2688 |
* |
| 2689 |
* async.waterfall([ |
| 2690 |
* async.constant(filename, "utf8"), |
| 2691 |
* fs.readFile, |
| 2692 |
* function (fileData, next) { |
| 2693 |
* //... |
| 2694 |
* } |
| 2695 |
* //... |
| 2696 |
* ], callback); |
| 2697 |
* |
| 2698 |
* async.auto({ |
| 2699 |
* hostname: async.constant("https://server.net/"), |
| 2700 |
* port: findFreePort, |
| 2701 |
* launchServer: ["hostname", "port", function (options, cb) { |
| 2702 |
* startServer(options, cb); |
| 2703 |
* }], |
| 2704 |
* //... |
| 2705 |
* }, callback); |
| 2706 |
*/ |
| 2707 |
var constant = function(/*...values*/) { |
| 2708 |
var values = slice(arguments); |
| 2709 |
var args = [null].concat(values); |
| 2710 |
return function (/*...ignoredArgs, callback*/) { |
| 2711 |
var callback = arguments[arguments.length - 1]; |
| 2712 |
return callback.apply(this, args); |
| 2713 |
}; |
| 2714 |
}; |
| 2715 |
|
| 2716 |
/** |
| 2717 |
* This method returns the first argument it receives. |
| 2718 |
* |
| 2719 |
* @static |
| 2720 |
* @since 0.1.0 |
| 2721 |
* @memberOf _ |
| 2722 |
* @category Util |
| 2723 |
* @param {*} value Any value. |
| 2724 |
* @returns {*} Returns `value`. |
| 2725 |
* @example |
| 2726 |
* |
| 2727 |
* var object = { 'a': 1 }; |
| 2728 |
* |
| 2729 |
* console.log(_.identity(object) === object); |
| 2730 |
* // => true |
| 2731 |
*/ |
| 2732 |
function identity(value) { |
| 2733 |
return value; |
| 2734 |
} |
| 2735 |
|
| 2736 |
function _createTester(check, getResult) { |
| 2737 |
return function(eachfn, arr, iteratee, cb) { |
| 2738 |
cb = cb || noop; |
| 2739 |
var testPassed = false; |
| 2740 |
var testResult; |
| 2741 |
eachfn(arr, function(value, _, callback) { |
| 2742 |
iteratee(value, function(err, result) { |
| 2743 |
if (err) { |
| 2744 |
callback(err); |
| 2745 |
} else if (check(result) && !testResult) { |
| 2746 |
testPassed = true; |
| 2747 |
testResult = getResult(true, value); |
| 2748 |
callback(null, breakLoop); |
| 2749 |
} else { |
| 2750 |
callback(); |
| 2751 |
} |
| 2752 |
}); |
| 2753 |
}, function(err) { |
| 2754 |
if (err) { |
| 2755 |
cb(err); |
| 2756 |
} else { |
| 2757 |
cb(null, testPassed ? testResult : getResult(false)); |
| 2758 |
} |
| 2759 |
}); |
| 2760 |
}; |
| 2761 |
} |
| 2762 |
|
| 2763 |
function _findGetResult(v, x) { |
| 2764 |
return x; |
| 2765 |
} |
| 2766 |
|
| 2767 |
/** |
| 2768 |
* Returns the first value in `coll` that passes an async truth test. The |
| 2769 |
* `iteratee` is applied in parallel, meaning the first iteratee to return |
| 2770 |
* `true` will fire the detect `callback` with that result. That means the |
| 2771 |
* result might not be the first item in the original `coll` (in terms of order) |
| 2772 |
* that passes the test. |
| 2773 |
|
| 2774 |
* If order within the original `coll` is important, then look at |
| 2775 |
* [`detectSeries`]{@link module:Collections.detectSeries}. |
| 2776 |
* |
| 2777 |
* @name detect |
| 2778 |
* @static |
| 2779 |
* @memberOf module:Collections |
| 2780 |
* @method |
| 2781 |
* @alias find |
| 2782 |
* @category Collections |
| 2783 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 2784 |
* @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. |
| 2785 |
* The iteratee must complete with a boolean value as its result. |
| 2786 |
* Invoked with (item, callback). |
| 2787 |
* @param {Function} [callback] - A callback which is called as soon as any |
| 2788 |
* iteratee returns `true`, or after all the `iteratee` functions have finished. |
| 2789 |
* Result will be the first item in the array that passes the truth test |
| 2790 |
* (iteratee) or the value `undefined` if none passed. Invoked with |
| 2791 |
* (err, result). |
| 2792 |
* @example |
| 2793 |
* |
| 2794 |
* async.detect(['file1','file2','file3'], function(filePath, callback) { |
| 2795 |
* fs.access(filePath, function(err) { |
| 2796 |
* callback(null, !err) |
| 2797 |
* }); |
| 2798 |
* }, function(err, result) { |
| 2799 |
* // result now equals the first file in the list that exists |
| 2800 |
* }); |
| 2801 |
*/ |
| 2802 |
var detect = doParallel(_createTester(identity, _findGetResult)); |
| 2803 |
|
| 2804 |
/** |
| 2805 |
* The same as [`detect`]{@link module:Collections.detect} but runs a maximum of `limit` async operations at a |
| 2806 |
* time. |
| 2807 |
* |
| 2808 |
* @name detectLimit |
| 2809 |
* @static |
| 2810 |
* @memberOf module:Collections |
| 2811 |
* @method |
| 2812 |
* @see [async.detect]{@link module:Collections.detect} |
| 2813 |
* @alias findLimit |
| 2814 |
* @category Collections |
| 2815 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 2816 |
* @param {number} limit - The maximum number of async operations at a time. |
| 2817 |
* @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. |
| 2818 |
* The iteratee must complete with a boolean value as its result. |
| 2819 |
* Invoked with (item, callback). |
| 2820 |
* @param {Function} [callback] - A callback which is called as soon as any |
| 2821 |
* iteratee returns `true`, or after all the `iteratee` functions have finished. |
| 2822 |
* Result will be the first item in the array that passes the truth test |
| 2823 |
* (iteratee) or the value `undefined` if none passed. Invoked with |
| 2824 |
* (err, result). |
| 2825 |
*/ |
| 2826 |
var detectLimit = doParallelLimit(_createTester(identity, _findGetResult)); |
| 2827 |
|
| 2828 |
/** |
| 2829 |
* The same as [`detect`]{@link module:Collections.detect} but runs only a single async operation at a time. |
| 2830 |
* |
| 2831 |
* @name detectSeries |
| 2832 |
* @static |
| 2833 |
* @memberOf module:Collections |
| 2834 |
* @method |
| 2835 |
* @see [async.detect]{@link module:Collections.detect} |
| 2836 |
* @alias findSeries |
| 2837 |
* @category Collections |
| 2838 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 2839 |
* @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`. |
| 2840 |
* The iteratee must complete with a boolean value as its result. |
| 2841 |
* Invoked with (item, callback). |
| 2842 |
* @param {Function} [callback] - A callback which is called as soon as any |
| 2843 |
* iteratee returns `true`, or after all the `iteratee` functions have finished. |
| 2844 |
* Result will be the first item in the array that passes the truth test |
| 2845 |
* (iteratee) or the value `undefined` if none passed. Invoked with |
| 2846 |
* (err, result). |
| 2847 |
*/ |
| 2848 |
var detectSeries = doLimit(detectLimit, 1); |
| 2849 |
|
| 2850 |
function consoleFunc(name) { |
| 2851 |
return function (fn/*, ...args*/) { |
| 2852 |
var args = slice(arguments, 1); |
| 2853 |
args.push(function (err/*, ...args*/) { |
| 2854 |
var args = slice(arguments, 1); |
| 2855 |
if (typeof console === 'object') { |
| 2856 |
if (err) { |
| 2857 |
if (console.error) { |
| 2858 |
console.error(err); |
| 2859 |
} |
| 2860 |
} else if (console[name]) { |
| 2861 |
arrayEach(args, function (x) { |
| 2862 |
console[name](x); |
| 2863 |
}); |
| 2864 |
} |
| 2865 |
} |
| 2866 |
}); |
| 2867 |
wrapAsync(fn).apply(null, args); |
| 2868 |
}; |
| 2869 |
} |
| 2870 |
|
| 2871 |
/** |
| 2872 |
* Logs the result of an [`async` function]{@link AsyncFunction} to the |
| 2873 |
* `console` using `console.dir` to display the properties of the resulting object. |
| 2874 |
* Only works in Node.js or in browsers that support `console.dir` and |
| 2875 |
* `console.error` (such as FF and Chrome). |
| 2876 |
* If multiple arguments are returned from the async function, |
| 2877 |
* `console.dir` is called on each argument in order. |
| 2878 |
* |
| 2879 |
* @name dir |
| 2880 |
* @static |
| 2881 |
* @memberOf module:Utils |
| 2882 |
* @method |
| 2883 |
* @category Util |
| 2884 |
* @param {AsyncFunction} function - The function you want to eventually apply |
| 2885 |
* all arguments to. |
| 2886 |
* @param {...*} arguments... - Any number of arguments to apply to the function. |
| 2887 |
* @example |
| 2888 |
* |
| 2889 |
* // in a module |
| 2890 |
* var hello = function(name, callback) { |
| 2891 |
* setTimeout(function() { |
| 2892 |
* callback(null, {hello: name}); |
| 2893 |
* }, 1000); |
| 2894 |
* }; |
| 2895 |
* |
| 2896 |
* // in the node repl |
| 2897 |
* node> async.dir(hello, 'world'); |
| 2898 |
* {hello: 'world'} |
| 2899 |
*/ |
| 2900 |
var dir = consoleFunc('dir'); |
| 2901 |
|
| 2902 |
/** |
| 2903 |
* The post-check version of [`during`]{@link module:ControlFlow.during}. To reflect the difference in |
| 2904 |
* the order of operations, the arguments `test` and `fn` are switched. |
| 2905 |
* |
| 2906 |
* Also a version of [`doWhilst`]{@link module:ControlFlow.doWhilst} with asynchronous `test` function. |
| 2907 |
* @name doDuring |
| 2908 |
* @static |
| 2909 |
* @memberOf module:ControlFlow |
| 2910 |
* @method |
| 2911 |
* @see [async.during]{@link module:ControlFlow.during} |
| 2912 |
* @category Control Flow |
| 2913 |
* @param {AsyncFunction} fn - An async function which is called each time |
| 2914 |
* `test` passes. Invoked with (callback). |
| 2915 |
* @param {AsyncFunction} test - asynchronous truth test to perform before each |
| 2916 |
* execution of `fn`. Invoked with (...args, callback), where `...args` are the |
| 2917 |
* non-error args from the previous callback of `fn`. |
| 2918 |
* @param {Function} [callback] - A callback which is called after the test |
| 2919 |
* function has failed and repeated execution of `fn` has stopped. `callback` |
| 2920 |
* will be passed an error if one occurred, otherwise `null`. |
| 2921 |
*/ |
| 2922 |
function doDuring(fn, test, callback) { |
| 2923 |
callback = onlyOnce(callback || noop); |
| 2924 |
var _fn = wrapAsync(fn); |
| 2925 |
var _test = wrapAsync(test); |
| 2926 |
|
| 2927 |
function next(err/*, ...args*/) { |
| 2928 |
if (err) return callback(err); |
| 2929 |
var args = slice(arguments, 1); |
| 2930 |
args.push(check); |
| 2931 |
_test.apply(this, args); |
| 2932 |
} |
| 2933 |
|
| 2934 |
function check(err, truth) { |
| 2935 |
if (err) return callback(err); |
| 2936 |
if (!truth) return callback(null); |
| 2937 |
_fn(next); |
| 2938 |
} |
| 2939 |
|
| 2940 |
check(null, true); |
| 2941 |
|
| 2942 |
} |
| 2943 |
|
| 2944 |
/** |
| 2945 |
* The post-check version of [`whilst`]{@link module:ControlFlow.whilst}. To reflect the difference in |
| 2946 |
* the order of operations, the arguments `test` and `iteratee` are switched. |
| 2947 |
* |
| 2948 |
* `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. |
| 2949 |
* |
| 2950 |
* @name doWhilst |
| 2951 |
* @static |
| 2952 |
* @memberOf module:ControlFlow |
| 2953 |
* @method |
| 2954 |
* @see [async.whilst]{@link module:ControlFlow.whilst} |
| 2955 |
* @category Control Flow |
| 2956 |
* @param {AsyncFunction} iteratee - A function which is called each time `test` |
| 2957 |
* passes. Invoked with (callback). |
| 2958 |
* @param {Function} test - synchronous truth test to perform after each |
| 2959 |
* execution of `iteratee`. Invoked with any non-error callback results of |
| 2960 |
* `iteratee`. |
| 2961 |
* @param {Function} [callback] - A callback which is called after the test |
| 2962 |
* function has failed and repeated execution of `iteratee` has stopped. |
| 2963 |
* `callback` will be passed an error and any arguments passed to the final |
| 2964 |
* `iteratee`'s callback. Invoked with (err, [results]); |
| 2965 |
*/ |
| 2966 |
function doWhilst(iteratee, test, callback) { |
| 2967 |
callback = onlyOnce(callback || noop); |
| 2968 |
var _iteratee = wrapAsync(iteratee); |
| 2969 |
var next = function(err/*, ...args*/) { |
| 2970 |
if (err) return callback(err); |
| 2971 |
var args = slice(arguments, 1); |
| 2972 |
if (test.apply(this, args)) return _iteratee(next); |
| 2973 |
callback.apply(null, [null].concat(args)); |
| 2974 |
}; |
| 2975 |
_iteratee(next); |
| 2976 |
} |
| 2977 |
|
| 2978 |
/** |
| 2979 |
* Like ['doWhilst']{@link module:ControlFlow.doWhilst}, except the `test` is inverted. Note the |
| 2980 |
* argument ordering differs from `until`. |
| 2981 |
* |
| 2982 |
* @name doUntil |
| 2983 |
* @static |
| 2984 |
* @memberOf module:ControlFlow |
| 2985 |
* @method |
| 2986 |
* @see [async.doWhilst]{@link module:ControlFlow.doWhilst} |
| 2987 |
* @category Control Flow |
| 2988 |
* @param {AsyncFunction} iteratee - An async function which is called each time |
| 2989 |
* `test` fails. Invoked with (callback). |
| 2990 |
* @param {Function} test - synchronous truth test to perform after each |
| 2991 |
* execution of `iteratee`. Invoked with any non-error callback results of |
| 2992 |
* `iteratee`. |
| 2993 |
* @param {Function} [callback] - A callback which is called after the test |
| 2994 |
* function has passed and repeated execution of `iteratee` has stopped. `callback` |
| 2995 |
* will be passed an error and any arguments passed to the final `iteratee`'s |
| 2996 |
* callback. Invoked with (err, [results]); |
| 2997 |
*/ |
| 2998 |
function doUntil(iteratee, test, callback) { |
| 2999 |
doWhilst(iteratee, function() { |
| 3000 |
return !test.apply(this, arguments); |
| 3001 |
}, callback); |
| 3002 |
} |
| 3003 |
|
| 3004 |
/** |
| 3005 |
* Like [`whilst`]{@link module:ControlFlow.whilst}, except the `test` is an asynchronous function that |
| 3006 |
* is passed a callback in the form of `function (err, truth)`. If error is |
| 3007 |
* passed to `test` or `fn`, the main callback is immediately called with the |
| 3008 |
* value of the error. |
| 3009 |
* |
| 3010 |
* @name during |
| 3011 |
* @static |
| 3012 |
* @memberOf module:ControlFlow |
| 3013 |
* @method |
| 3014 |
* @see [async.whilst]{@link module:ControlFlow.whilst} |
| 3015 |
* @category Control Flow |
| 3016 |
* @param {AsyncFunction} test - asynchronous truth test to perform before each |
| 3017 |
* execution of `fn`. Invoked with (callback). |
| 3018 |
* @param {AsyncFunction} fn - An async function which is called each time |
| 3019 |
* `test` passes. Invoked with (callback). |
| 3020 |
* @param {Function} [callback] - A callback which is called after the test |
| 3021 |
* function has failed and repeated execution of `fn` has stopped. `callback` |
| 3022 |
* will be passed an error, if one occurred, otherwise `null`. |
| 3023 |
* @example |
| 3024 |
* |
| 3025 |
* var count = 0; |
| 3026 |
* |
| 3027 |
* async.during( |
| 3028 |
* function (callback) { |
| 3029 |
* return callback(null, count < 5); |
| 3030 |
* }, |
| 3031 |
* function (callback) { |
| 3032 |
* count++; |
| 3033 |
* setTimeout(callback, 1000); |
| 3034 |
* }, |
| 3035 |
* function (err) { |
| 3036 |
* // 5 seconds have passed |
| 3037 |
* } |
| 3038 |
* ); |
| 3039 |
*/ |
| 3040 |
function during(test, fn, callback) { |
| 3041 |
callback = onlyOnce(callback || noop); |
| 3042 |
var _fn = wrapAsync(fn); |
| 3043 |
var _test = wrapAsync(test); |
| 3044 |
|
| 3045 |
function next(err) { |
| 3046 |
if (err) return callback(err); |
| 3047 |
_test(check); |
| 3048 |
} |
| 3049 |
|
| 3050 |
function check(err, truth) { |
| 3051 |
if (err) return callback(err); |
| 3052 |
if (!truth) return callback(null); |
| 3053 |
_fn(next); |
| 3054 |
} |
| 3055 |
|
| 3056 |
_test(check); |
| 3057 |
} |
| 3058 |
|
| 3059 |
function _withoutIndex(iteratee) { |
| 3060 |
return function (value, index, callback) { |
| 3061 |
return iteratee(value, callback); |
| 3062 |
}; |
| 3063 |
} |
| 3064 |
|
| 3065 |
/** |
| 3066 |
* Applies the function `iteratee` to each item in `coll`, in parallel. |
| 3067 |
* The `iteratee` is called with an item from the list, and a callback for when |
| 3068 |
* it has finished. If the `iteratee` passes an error to its `callback`, the |
| 3069 |
* main `callback` (for the `each` function) is immediately called with the |
| 3070 |
* error. |
| 3071 |
* |
| 3072 |
* Note, that since this function applies `iteratee` to each item in parallel, |
| 3073 |
* there is no guarantee that the iteratee functions will complete in order. |
| 3074 |
* |
| 3075 |
* @name each |
| 3076 |
* @static |
| 3077 |
* @memberOf module:Collections |
| 3078 |
* @method |
| 3079 |
* @alias forEach |
| 3080 |
* @category Collection |
| 3081 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 3082 |
* @param {AsyncFunction} iteratee - An async function to apply to |
| 3083 |
* each item in `coll`. Invoked with (item, callback). |
| 3084 |
* The array index is not passed to the iteratee. |
| 3085 |
* If you need the index, use `eachOf`. |
| 3086 |
* @param {Function} [callback] - A callback which is called when all |
| 3087 |
* `iteratee` functions have finished, or an error occurs. Invoked with (err). |
| 3088 |
* @example |
| 3089 |
* |
| 3090 |
* // assuming openFiles is an array of file names and saveFile is a function |
| 3091 |
* // to save the modified contents of that file: |
| 3092 |
* |
| 3093 |
* async.each(openFiles, saveFile, function(err){ |
| 3094 |
* // if any of the saves produced an error, err would equal that error |
| 3095 |
* }); |
| 3096 |
* |
| 3097 |
* // assuming openFiles is an array of file names |
| 3098 |
* async.each(openFiles, function(file, callback) { |
| 3099 |
* |
| 3100 |
* // Perform operation on file here. |
| 3101 |
* console.log('Processing file ' + file); |
| 3102 |
* |
| 3103 |
* if( file.length > 32 ) { |
| 3104 |
* console.log('This file name is too long'); |
| 3105 |
* callback('File name too long'); |
| 3106 |
* } else { |
| 3107 |
* // Do work to process file here |
| 3108 |
* console.log('File processed'); |
| 3109 |
* callback(); |
| 3110 |
* } |
| 3111 |
* }, function(err) { |
| 3112 |
* // if any of the file processing produced an error, err would equal that error |
| 3113 |
* if( err ) { |
| 3114 |
* // One of the iterations produced an error. |
| 3115 |
* // All processing will now stop. |
| 3116 |
* console.log('A file failed to process'); |
| 3117 |
* } else { |
| 3118 |
* console.log('All files have been processed successfully'); |
| 3119 |
* } |
| 3120 |
* }); |
| 3121 |
*/ |
| 3122 |
function eachLimit(coll, iteratee, callback) { |
| 3123 |
eachOf(coll, _withoutIndex(wrapAsync(iteratee)), callback); |
| 3124 |
} |
| 3125 |
|
| 3126 |
/** |
| 3127 |
* The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time. |
| 3128 |
* |
| 3129 |
* @name eachLimit |
| 3130 |
* @static |
| 3131 |
* @memberOf module:Collections |
| 3132 |
* @method |
| 3133 |
* @see [async.each]{@link module:Collections.each} |
| 3134 |
* @alias forEachLimit |
| 3135 |
* @category Collection |
| 3136 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 3137 |
* @param {number} limit - The maximum number of async operations at a time. |
| 3138 |
* @param {AsyncFunction} iteratee - An async function to apply to each item in |
| 3139 |
* `coll`. |
| 3140 |
* The array index is not passed to the iteratee. |
| 3141 |
* If you need the index, use `eachOfLimit`. |
| 3142 |
* Invoked with (item, callback). |
| 3143 |
* @param {Function} [callback] - A callback which is called when all |
| 3144 |
* `iteratee` functions have finished, or an error occurs. Invoked with (err). |
| 3145 |
*/ |
| 3146 |
function eachLimit$1(coll, limit, iteratee, callback) { |
| 3147 |
_eachOfLimit(limit)(coll, _withoutIndex(wrapAsync(iteratee)), callback); |
| 3148 |
} |
| 3149 |
|
| 3150 |
/** |
| 3151 |
* The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time. |
| 3152 |
* |
| 3153 |
* @name eachSeries |
| 3154 |
* @static |
| 3155 |
* @memberOf module:Collections |
| 3156 |
* @method |
| 3157 |
* @see [async.each]{@link module:Collections.each} |
| 3158 |
* @alias forEachSeries |
| 3159 |
* @category Collection |
| 3160 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 3161 |
* @param {AsyncFunction} iteratee - An async function to apply to each |
| 3162 |
* item in `coll`. |
| 3163 |
* The array index is not passed to the iteratee. |
| 3164 |
* If you need the index, use `eachOfSeries`. |
| 3165 |
* Invoked with (item, callback). |
| 3166 |
* @param {Function} [callback] - A callback which is called when all |
| 3167 |
* `iteratee` functions have finished, or an error occurs. Invoked with (err). |
| 3168 |
*/ |
| 3169 |
var eachSeries = doLimit(eachLimit$1, 1); |
| 3170 |
|
| 3171 |
/** |
| 3172 |
* Wrap an async function and ensure it calls its callback on a later tick of |
| 3173 |
* the event loop. If the function already calls its callback on a next tick, |
| 3174 |
* no extra deferral is added. This is useful for preventing stack overflows |
| 3175 |
* (`RangeError: Maximum call stack size exceeded`) and generally keeping |
| 3176 |
* [Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony) |
| 3177 |
* contained. ES2017 `async` functions are returned as-is -- they are immune |
| 3178 |
* to Zalgo's corrupting influences, as they always resolve on a later tick. |
| 3179 |
* |
| 3180 |
* @name ensureAsync |
| 3181 |
* @static |
| 3182 |
* @memberOf module:Utils |
| 3183 |
* @method |
| 3184 |
* @category Util |
| 3185 |
* @param {AsyncFunction} fn - an async function, one that expects a node-style |
| 3186 |
* callback as its last argument. |
| 3187 |
* @returns {AsyncFunction} Returns a wrapped function with the exact same call |
| 3188 |
* signature as the function passed in. |
| 3189 |
* @example |
| 3190 |
* |
| 3191 |
* function sometimesAsync(arg, callback) { |
| 3192 |
* if (cache[arg]) { |
| 3193 |
* return callback(null, cache[arg]); // this would be synchronous!! |
| 3194 |
* } else { |
| 3195 |
* doSomeIO(arg, callback); // this IO would be asynchronous |
| 3196 |
* } |
| 3197 |
* } |
| 3198 |
* |
| 3199 |
* // this has a risk of stack overflows if many results are cached in a row |
| 3200 |
* async.mapSeries(args, sometimesAsync, done); |
| 3201 |
* |
| 3202 |
* // this will defer sometimesAsync's callback if necessary, |
| 3203 |
* // preventing stack overflows |
| 3204 |
* async.mapSeries(args, async.ensureAsync(sometimesAsync), done); |
| 3205 |
*/ |
| 3206 |
function ensureAsync(fn) { |
| 3207 |
if (isAsync(fn)) return fn; |
| 3208 |
return initialParams(function (args, callback) { |
| 3209 |
var sync = true; |
| 3210 |
args.push(function () { |
| 3211 |
var innerArgs = arguments; |
| 3212 |
if (sync) { |
| 3213 |
setImmediate$1(function () { |
| 3214 |
callback.apply(null, innerArgs); |
| 3215 |
}); |
| 3216 |
} else { |
| 3217 |
callback.apply(null, innerArgs); |
| 3218 |
} |
| 3219 |
}); |
| 3220 |
fn.apply(this, args); |
| 3221 |
sync = false; |
| 3222 |
}); |
| 3223 |
} |
| 3224 |
|
| 3225 |
function notId(v) { |
| 3226 |
return !v; |
| 3227 |
} |
| 3228 |
|
| 3229 |
/** |
| 3230 |
* Returns `true` if every element in `coll` satisfies an async test. If any |
| 3231 |
* iteratee call returns `false`, the main `callback` is immediately called. |
| 3232 |
* |
| 3233 |
* @name every |
| 3234 |
* @static |
| 3235 |
* @memberOf module:Collections |
| 3236 |
* @method |
| 3237 |
* @alias all |
| 3238 |
* @category Collection |
| 3239 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 3240 |
* @param {AsyncFunction} iteratee - An async truth test to apply to each item |
| 3241 |
* in the collection in parallel. |
| 3242 |
* The iteratee must complete with a boolean result value. |
| 3243 |
* Invoked with (item, callback). |
| 3244 |
* @param {Function} [callback] - A callback which is called after all the |
| 3245 |
* `iteratee` functions have finished. Result will be either `true` or `false` |
| 3246 |
* depending on the values of the async tests. Invoked with (err, result). |
| 3247 |
* @example |
| 3248 |
* |
| 3249 |
* async.every(['file1','file2','file3'], function(filePath, callback) { |
| 3250 |
* fs.access(filePath, function(err) { |
| 3251 |
* callback(null, !err) |
| 3252 |
* }); |
| 3253 |
* }, function(err, result) { |
| 3254 |
* // if result is true then every file exists |
| 3255 |
* }); |
| 3256 |
*/ |
| 3257 |
var every = doParallel(_createTester(notId, notId)); |
| 3258 |
|
| 3259 |
/** |
| 3260 |
* The same as [`every`]{@link module:Collections.every} but runs a maximum of `limit` async operations at a time. |
| 3261 |
* |
| 3262 |
* @name everyLimit |
| 3263 |
* @static |
| 3264 |
* @memberOf module:Collections |
| 3265 |
* @method |
| 3266 |
* @see [async.every]{@link module:Collections.every} |
| 3267 |
* @alias allLimit |
| 3268 |
* @category Collection |
| 3269 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 3270 |
* @param {number} limit - The maximum number of async operations at a time. |
| 3271 |
* @param {AsyncFunction} iteratee - An async truth test to apply to each item |
| 3272 |
* in the collection in parallel. |
| 3273 |
* The iteratee must complete with a boolean result value. |
| 3274 |
* Invoked with (item, callback). |
| 3275 |
* @param {Function} [callback] - A callback which is called after all the |
| 3276 |
* `iteratee` functions have finished. Result will be either `true` or `false` |
| 3277 |
* depending on the values of the async tests. Invoked with (err, result). |
| 3278 |
*/ |
| 3279 |
var everyLimit = doParallelLimit(_createTester(notId, notId)); |
| 3280 |
|
| 3281 |
/** |
| 3282 |
* The same as [`every`]{@link module:Collections.every} but runs only a single async operation at a time. |
| 3283 |
* |
| 3284 |
* @name everySeries |
| 3285 |
* @static |
| 3286 |
* @memberOf module:Collections |
| 3287 |
* @method |
| 3288 |
* @see [async.every]{@link module:Collections.every} |
| 3289 |
* @alias allSeries |
| 3290 |
* @category Collection |
| 3291 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 3292 |
* @param {AsyncFunction} iteratee - An async truth test to apply to each item |
| 3293 |
* in the collection in series. |
| 3294 |
* The iteratee must complete with a boolean result value. |
| 3295 |
* Invoked with (item, callback). |
| 3296 |
* @param {Function} [callback] - A callback which is called after all the |
| 3297 |
* `iteratee` functions have finished. Result will be either `true` or `false` |
| 3298 |
* depending on the values of the async tests. Invoked with (err, result). |
| 3299 |
*/ |
| 3300 |
var everySeries = doLimit(everyLimit, 1); |
| 3301 |
|
| 3302 |
/** |
| 3303 |
* The base implementation of `_.property` without support for deep paths. |
| 3304 |
* |
| 3305 |
* @private |
| 3306 |
* @param {string} key The key of the property to get. |
| 3307 |
* @returns {Function} Returns the new accessor function. |
| 3308 |
*/ |
| 3309 |
function baseProperty(key) { |
| 3310 |
return function(object) { |
| 3311 |
return object == null ? undefined : object[key]; |
| 3312 |
}; |
| 3313 |
} |
| 3314 |
|
| 3315 |
function filterArray(eachfn, arr, iteratee, callback) { |
| 3316 |
var truthValues = new Array(arr.length); |
| 3317 |
eachfn(arr, function (x, index, callback) { |
| 3318 |
iteratee(x, function (err, v) { |
| 3319 |
truthValues[index] = !!v; |
| 3320 |
callback(err); |
| 3321 |
}); |
| 3322 |
}, function (err) { |
| 3323 |
if (err) return callback(err); |
| 3324 |
var results = []; |
| 3325 |
for (var i = 0; i < arr.length; i++) { |
| 3326 |
if (truthValues[i]) results.push(arr[i]); |
| 3327 |
} |
| 3328 |
callback(null, results); |
| 3329 |
}); |
| 3330 |
} |
| 3331 |
|
| 3332 |
function filterGeneric(eachfn, coll, iteratee, callback) { |
| 3333 |
var results = []; |
| 3334 |
eachfn(coll, function (x, index, callback) { |
| 3335 |
iteratee(x, function (err, v) { |
| 3336 |
if (err) { |
| 3337 |
callback(err); |
| 3338 |
} else { |
| 3339 |
if (v) { |
| 3340 |
results.push({index: index, value: x}); |
| 3341 |
} |
| 3342 |
callback(); |
| 3343 |
} |
| 3344 |
}); |
| 3345 |
}, function (err) { |
| 3346 |
if (err) { |
| 3347 |
callback(err); |
| 3348 |
} else { |
| 3349 |
callback(null, arrayMap(results.sort(function (a, b) { |
| 3350 |
return a.index - b.index; |
| 3351 |
}), baseProperty('value'))); |
| 3352 |
} |
| 3353 |
}); |
| 3354 |
} |
| 3355 |
|
| 3356 |
function _filter(eachfn, coll, iteratee, callback) { |
| 3357 |
var filter = isArrayLike(coll) ? filterArray : filterGeneric; |
| 3358 |
filter(eachfn, coll, wrapAsync(iteratee), callback || noop); |
| 3359 |
} |
| 3360 |
|
| 3361 |
/** |
| 3362 |
* Returns a new array of all the values in `coll` which pass an async truth |
| 3363 |
* test. This operation is performed in parallel, but the results array will be |
| 3364 |
* in the same order as the original. |
| 3365 |
* |
| 3366 |
* @name filter |
| 3367 |
* @static |
| 3368 |
* @memberOf module:Collections |
| 3369 |
* @method |
| 3370 |
* @alias select |
| 3371 |
* @category Collection |
| 3372 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 3373 |
* @param {Function} iteratee - A truth test to apply to each item in `coll`. |
| 3374 |
* The `iteratee` is passed a `callback(err, truthValue)`, which must be called |
| 3375 |
* with a boolean argument once it has completed. Invoked with (item, callback). |
| 3376 |
* @param {Function} [callback] - A callback which is called after all the |
| 3377 |
* `iteratee` functions have finished. Invoked with (err, results). |
| 3378 |
* @example |
| 3379 |
* |
| 3380 |
* async.filter(['file1','file2','file3'], function(filePath, callback) { |
| 3381 |
* fs.access(filePath, function(err) { |
| 3382 |
* callback(null, !err) |
| 3383 |
* }); |
| 3384 |
* }, function(err, results) { |
| 3385 |
* // results now equals an array of the existing files |
| 3386 |
* }); |
| 3387 |
*/ |
| 3388 |
var filter = doParallel(_filter); |
| 3389 |
|
| 3390 |
/** |
| 3391 |
* The same as [`filter`]{@link module:Collections.filter} but runs a maximum of `limit` async operations at a |
| 3392 |
* time. |
| 3393 |
* |
| 3394 |
* @name filterLimit |
| 3395 |
* @static |
| 3396 |
* @memberOf module:Collections |
| 3397 |
* @method |
| 3398 |
* @see [async.filter]{@link module:Collections.filter} |
| 3399 |
* @alias selectLimit |
| 3400 |
* @category Collection |
| 3401 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 3402 |
* @param {number} limit - The maximum number of async operations at a time. |
| 3403 |
* @param {Function} iteratee - A truth test to apply to each item in `coll`. |
| 3404 |
* The `iteratee` is passed a `callback(err, truthValue)`, which must be called |
| 3405 |
* with a boolean argument once it has completed. Invoked with (item, callback). |
| 3406 |
* @param {Function} [callback] - A callback which is called after all the |
| 3407 |
* `iteratee` functions have finished. Invoked with (err, results). |
| 3408 |
*/ |
| 3409 |
var filterLimit = doParallelLimit(_filter); |
| 3410 |
|
| 3411 |
/** |
| 3412 |
* The same as [`filter`]{@link module:Collections.filter} but runs only a single async operation at a time. |
| 3413 |
* |
| 3414 |
* @name filterSeries |
| 3415 |
* @static |
| 3416 |
* @memberOf module:Collections |
| 3417 |
* @method |
| 3418 |
* @see [async.filter]{@link module:Collections.filter} |
| 3419 |
* @alias selectSeries |
| 3420 |
* @category Collection |
| 3421 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 3422 |
* @param {Function} iteratee - A truth test to apply to each item in `coll`. |
| 3423 |
* The `iteratee` is passed a `callback(err, truthValue)`, which must be called |
| 3424 |
* with a boolean argument once it has completed. Invoked with (item, callback). |
| 3425 |
* @param {Function} [callback] - A callback which is called after all the |
| 3426 |
* `iteratee` functions have finished. Invoked with (err, results) |
| 3427 |
*/ |
| 3428 |
var filterSeries = doLimit(filterLimit, 1); |
| 3429 |
|
| 3430 |
/** |
| 3431 |
* Calls the asynchronous function `fn` with a callback parameter that allows it |
| 3432 |
* to call itself again, in series, indefinitely. |
| 3433 |
|
| 3434 |
* If an error is passed to the callback then `errback` is called with the |
| 3435 |
* error, and execution stops, otherwise it will never be called. |
| 3436 |
* |
| 3437 |
* @name forever |
| 3438 |
* @static |
| 3439 |
* @memberOf module:ControlFlow |
| 3440 |
* @method |
| 3441 |
* @category Control Flow |
| 3442 |
* @param {AsyncFunction} fn - an async function to call repeatedly. |
| 3443 |
* Invoked with (next). |
| 3444 |
* @param {Function} [errback] - when `fn` passes an error to it's callback, |
| 3445 |
* this function will be called, and execution stops. Invoked with (err). |
| 3446 |
* @example |
| 3447 |
* |
| 3448 |
* async.forever( |
| 3449 |
* function(next) { |
| 3450 |
* // next is suitable for passing to things that need a callback(err [, whatever]); |
| 3451 |
* // it will result in this function being called again. |
| 3452 |
* }, |
| 3453 |
* function(err) { |
| 3454 |
* // if next is called with a value in its first parameter, it will appear |
| 3455 |
* // in here as 'err', and execution will stop. |
| 3456 |
* } |
| 3457 |
* ); |
| 3458 |
*/ |
| 3459 |
function forever(fn, errback) { |
| 3460 |
var done = onlyOnce(errback || noop); |
| 3461 |
var task = wrapAsync(ensureAsync(fn)); |
| 3462 |
|
| 3463 |
function next(err) { |
| 3464 |
if (err) return done(err); |
| 3465 |
task(next); |
| 3466 |
} |
| 3467 |
next(); |
| 3468 |
} |
| 3469 |
|
| 3470 |
/** |
| 3471 |
* The same as [`groupBy`]{@link module:Collections.groupBy} but runs a maximum of `limit` async operations at a time. |
| 3472 |
* |
| 3473 |
* @name groupByLimit |
| 3474 |
* @static |
| 3475 |
* @memberOf module:Collections |
| 3476 |
* @method |
| 3477 |
* @see [async.groupBy]{@link module:Collections.groupBy} |
| 3478 |
* @category Collection |
| 3479 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 3480 |
* @param {number} limit - The maximum number of async operations at a time. |
| 3481 |
* @param {AsyncFunction} iteratee - An async function to apply to each item in |
| 3482 |
* `coll`. |
| 3483 |
* The iteratee should complete with a `key` to group the value under. |
| 3484 |
* Invoked with (value, callback). |
| 3485 |
* @param {Function} [callback] - A callback which is called when all `iteratee` |
| 3486 |
* functions have finished, or an error occurs. Result is an `Object` whoses |
| 3487 |
* properties are arrays of values which returned the corresponding key. |
| 3488 |
*/ |
| 3489 |
var groupByLimit = function(coll, limit, iteratee, callback) { |
| 3490 |
callback = callback || noop; |
| 3491 |
var _iteratee = wrapAsync(iteratee); |
| 3492 |
mapLimit(coll, limit, function(val, callback) { |
| 3493 |
_iteratee(val, function(err, key) { |
| 3494 |
if (err) return callback(err); |
| 3495 |
return callback(null, {key: key, val: val}); |
| 3496 |
}); |
| 3497 |
}, function(err, mapResults) { |
| 3498 |
var result = {}; |
| 3499 |
// from MDN, handle object having an `hasOwnProperty` prop |
| 3500 |
var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 3501 |
|
| 3502 |
for (var i = 0; i < mapResults.length; i++) { |
| 3503 |
if (mapResults[i]) { |
| 3504 |
var key = mapResults[i].key; |
| 3505 |
var val = mapResults[i].val; |
| 3506 |
|
| 3507 |
if (hasOwnProperty.call(result, key)) { |
| 3508 |
result[key].push(val); |
| 3509 |
} else { |
| 3510 |
result[key] = [val]; |
| 3511 |
} |
| 3512 |
} |
| 3513 |
} |
| 3514 |
|
| 3515 |
return callback(err, result); |
| 3516 |
}); |
| 3517 |
}; |
| 3518 |
|
| 3519 |
/** |
| 3520 |
* Returns a new object, where each value corresponds to an array of items, from |
| 3521 |
* `coll`, that returned the corresponding key. That is, the keys of the object |
| 3522 |
* correspond to the values passed to the `iteratee` callback. |
| 3523 |
* |
| 3524 |
* Note: Since this function applies the `iteratee` to each item in parallel, |
| 3525 |
* there is no guarantee that the `iteratee` functions will complete in order. |
| 3526 |
* However, the values for each key in the `result` will be in the same order as |
| 3527 |
* the original `coll`. For Objects, the values will roughly be in the order of |
| 3528 |
* the original Objects' keys (but this can vary across JavaScript engines). |
| 3529 |
* |
| 3530 |
* @name groupBy |
| 3531 |
* @static |
| 3532 |
* @memberOf module:Collections |
| 3533 |
* @method |
| 3534 |
* @category Collection |
| 3535 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 3536 |
* @param {AsyncFunction} iteratee - An async function to apply to each item in |
| 3537 |
* `coll`. |
| 3538 |
* The iteratee should complete with a `key` to group the value under. |
| 3539 |
* Invoked with (value, callback). |
| 3540 |
* @param {Function} [callback] - A callback which is called when all `iteratee` |
| 3541 |
* functions have finished, or an error occurs. Result is an `Object` whoses |
| 3542 |
* properties are arrays of values which returned the corresponding key. |
| 3543 |
* @example |
| 3544 |
* |
| 3545 |
* async.groupBy(['userId1', 'userId2', 'userId3'], function(userId, callback) { |
| 3546 |
* db.findById(userId, function(err, user) { |
| 3547 |
* if (err) return callback(err); |
| 3548 |
* return callback(null, user.age); |
| 3549 |
* }); |
| 3550 |
* }, function(err, result) { |
| 3551 |
* // result is object containing the userIds grouped by age |
| 3552 |
* // e.g. { 30: ['userId1', 'userId3'], 42: ['userId2']}; |
| 3553 |
* }); |
| 3554 |
*/ |
| 3555 |
var groupBy = doLimit(groupByLimit, Infinity); |
| 3556 |
|
| 3557 |
/** |
| 3558 |
* The same as [`groupBy`]{@link module:Collections.groupBy} but runs only a single async operation at a time. |
| 3559 |
* |
| 3560 |
* @name groupBySeries |
| 3561 |
* @static |
| 3562 |
* @memberOf module:Collections |
| 3563 |
* @method |
| 3564 |
* @see [async.groupBy]{@link module:Collections.groupBy} |
| 3565 |
* @category Collection |
| 3566 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 3567 |
* @param {number} limit - The maximum number of async operations at a time. |
| 3568 |
* @param {AsyncFunction} iteratee - An async function to apply to each item in |
| 3569 |
* `coll`. |
| 3570 |
* The iteratee should complete with a `key` to group the value under. |
| 3571 |
* Invoked with (value, callback). |
| 3572 |
* @param {Function} [callback] - A callback which is called when all `iteratee` |
| 3573 |
* functions have finished, or an error occurs. Result is an `Object` whoses |
| 3574 |
* properties are arrays of values which returned the corresponding key. |
| 3575 |
*/ |
| 3576 |
var groupBySeries = doLimit(groupByLimit, 1); |
| 3577 |
|
| 3578 |
/** |
| 3579 |
* Logs the result of an `async` function to the `console`. Only works in |
| 3580 |
* Node.js or in browsers that support `console.log` and `console.error` (such |
| 3581 |
* as FF and Chrome). If multiple arguments are returned from the async |
| 3582 |
* function, `console.log` is called on each argument in order. |
| 3583 |
* |
| 3584 |
* @name log |
| 3585 |
* @static |
| 3586 |
* @memberOf module:Utils |
| 3587 |
* @method |
| 3588 |
* @category Util |
| 3589 |
* @param {AsyncFunction} function - The function you want to eventually apply |
| 3590 |
* all arguments to. |
| 3591 |
* @param {...*} arguments... - Any number of arguments to apply to the function. |
| 3592 |
* @example |
| 3593 |
* |
| 3594 |
* // in a module |
| 3595 |
* var hello = function(name, callback) { |
| 3596 |
* setTimeout(function() { |
| 3597 |
* callback(null, 'hello ' + name); |
| 3598 |
* }, 1000); |
| 3599 |
* }; |
| 3600 |
* |
| 3601 |
* // in the node repl |
| 3602 |
* node> async.log(hello, 'world'); |
| 3603 |
* 'hello world' |
| 3604 |
*/ |
| 3605 |
var log = consoleFunc('log'); |
| 3606 |
|
| 3607 |
/** |
| 3608 |
* The same as [`mapValues`]{@link module:Collections.mapValues} but runs a maximum of `limit` async operations at a |
| 3609 |
* time. |
| 3610 |
* |
| 3611 |
* @name mapValuesLimit |
| 3612 |
* @static |
| 3613 |
* @memberOf module:Collections |
| 3614 |
* @method |
| 3615 |
* @see [async.mapValues]{@link module:Collections.mapValues} |
| 3616 |
* @category Collection |
| 3617 |
* @param {Object} obj - A collection to iterate over. |
| 3618 |
* @param {number} limit - The maximum number of async operations at a time. |
| 3619 |
* @param {AsyncFunction} iteratee - A function to apply to each value and key |
| 3620 |
* in `coll`. |
| 3621 |
* The iteratee should complete with the transformed value as its result. |
| 3622 |
* Invoked with (value, key, callback). |
| 3623 |
* @param {Function} [callback] - A callback which is called when all `iteratee` |
| 3624 |
* functions have finished, or an error occurs. `result` is a new object consisting |
| 3625 |
* of each key from `obj`, with each transformed value on the right-hand side. |
| 3626 |
* Invoked with (err, result). |
| 3627 |
*/ |
| 3628 |
function mapValuesLimit(obj, limit, iteratee, callback) { |
| 3629 |
callback = once(callback || noop); |
| 3630 |
var newObj = {}; |
| 3631 |
var _iteratee = wrapAsync(iteratee); |
| 3632 |
eachOfLimit(obj, limit, function(val, key, next) { |
| 3633 |
_iteratee(val, key, function (err, result) { |
| 3634 |
if (err) return next(err); |
| 3635 |
newObj[key] = result; |
| 3636 |
next(); |
| 3637 |
}); |
| 3638 |
}, function (err) { |
| 3639 |
callback(err, newObj); |
| 3640 |
}); |
| 3641 |
} |
| 3642 |
|
| 3643 |
/** |
| 3644 |
* A relative of [`map`]{@link module:Collections.map}, designed for use with objects. |
| 3645 |
* |
| 3646 |
* Produces a new Object by mapping each value of `obj` through the `iteratee` |
| 3647 |
* function. The `iteratee` is called each `value` and `key` from `obj` and a |
| 3648 |
* callback for when it has finished processing. Each of these callbacks takes |
| 3649 |
* two arguments: an `error`, and the transformed item from `obj`. If `iteratee` |
| 3650 |
* passes an error to its callback, the main `callback` (for the `mapValues` |
| 3651 |
* function) is immediately called with the error. |
| 3652 |
* |
| 3653 |
* Note, the order of the keys in the result is not guaranteed. The keys will |
| 3654 |
* be roughly in the order they complete, (but this is very engine-specific) |
| 3655 |
* |
| 3656 |
* @name mapValues |
| 3657 |
* @static |
| 3658 |
* @memberOf module:Collections |
| 3659 |
* @method |
| 3660 |
* @category Collection |
| 3661 |
* @param {Object} obj - A collection to iterate over. |
| 3662 |
* @param {AsyncFunction} iteratee - A function to apply to each value and key |
| 3663 |
* in `coll`. |
| 3664 |
* The iteratee should complete with the transformed value as its result. |
| 3665 |
* Invoked with (value, key, callback). |
| 3666 |
* @param {Function} [callback] - A callback which is called when all `iteratee` |
| 3667 |
* functions have finished, or an error occurs. `result` is a new object consisting |
| 3668 |
* of each key from `obj`, with each transformed value on the right-hand side. |
| 3669 |
* Invoked with (err, result). |
| 3670 |
* @example |
| 3671 |
* |
| 3672 |
* async.mapValues({ |
| 3673 |
* f1: 'file1', |
| 3674 |
* f2: 'file2', |
| 3675 |
* f3: 'file3' |
| 3676 |
* }, function (file, key, callback) { |
| 3677 |
* fs.stat(file, callback); |
| 3678 |
* }, function(err, result) { |
| 3679 |
* // result is now a map of stats for each file, e.g. |
| 3680 |
* // { |
| 3681 |
* // f1: [stats for file1], |
| 3682 |
* // f2: [stats for file2], |
| 3683 |
* // f3: [stats for file3] |
| 3684 |
* // } |
| 3685 |
* }); |
| 3686 |
*/ |
| 3687 |
|
| 3688 |
var mapValues = doLimit(mapValuesLimit, Infinity); |
| 3689 |
|
| 3690 |
/** |
| 3691 |
* The same as [`mapValues`]{@link module:Collections.mapValues} but runs only a single async operation at a time. |
| 3692 |
* |
| 3693 |
* @name mapValuesSeries |
| 3694 |
* @static |
| 3695 |
* @memberOf module:Collections |
| 3696 |
* @method |
| 3697 |
* @see [async.mapValues]{@link module:Collections.mapValues} |
| 3698 |
* @category Collection |
| 3699 |
* @param {Object} obj - A collection to iterate over. |
| 3700 |
* @param {AsyncFunction} iteratee - A function to apply to each value and key |
| 3701 |
* in `coll`. |
| 3702 |
* The iteratee should complete with the transformed value as its result. |
| 3703 |
* Invoked with (value, key, callback). |
| 3704 |
* @param {Function} [callback] - A callback which is called when all `iteratee` |
| 3705 |
* functions have finished, or an error occurs. `result` is a new object consisting |
| 3706 |
* of each key from `obj`, with each transformed value on the right-hand side. |
| 3707 |
* Invoked with (err, result). |
| 3708 |
*/ |
| 3709 |
var mapValuesSeries = doLimit(mapValuesLimit, 1); |
| 3710 |
|
| 3711 |
function has(obj, key) { |
| 3712 |
return key in obj; |
| 3713 |
} |
| 3714 |
|
| 3715 |
/** |
| 3716 |
* Caches the results of an async function. When creating a hash to store |
| 3717 |
* function results against, the callback is omitted from the hash and an |
| 3718 |
* optional hash function can be used. |
| 3719 |
* |
| 3720 |
* If no hash function is specified, the first argument is used as a hash key, |
| 3721 |
* which may work reasonably if it is a string or a data type that converts to a |
| 3722 |
* distinct string. Note that objects and arrays will not behave reasonably. |
| 3723 |
* Neither will cases where the other arguments are significant. In such cases, |
| 3724 |
* specify your own hash function. |
| 3725 |
* |
| 3726 |
* The cache of results is exposed as the `memo` property of the function |
| 3727 |
* returned by `memoize`. |
| 3728 |
* |
| 3729 |
* @name memoize |
| 3730 |
* @static |
| 3731 |
* @memberOf module:Utils |
| 3732 |
* @method |
| 3733 |
* @category Util |
| 3734 |
* @param {AsyncFunction} fn - The async function to proxy and cache results from. |
| 3735 |
* @param {Function} hasher - An optional function for generating a custom hash |
| 3736 |
* for storing results. It has all the arguments applied to it apart from the |
| 3737 |
* callback, and must be synchronous. |
| 3738 |
* @returns {AsyncFunction} a memoized version of `fn` |
| 3739 |
* @example |
| 3740 |
* |
| 3741 |
* var slow_fn = function(name, callback) { |
| 3742 |
* // do something |
| 3743 |
* callback(null, result); |
| 3744 |
* }; |
| 3745 |
* var fn = async.memoize(slow_fn); |
| 3746 |
* |
| 3747 |
* // fn can now be used as if it were slow_fn |
| 3748 |
* fn('some name', function() { |
| 3749 |
* // callback |
| 3750 |
* }); |
| 3751 |
*/ |
| 3752 |
function memoize(fn, hasher) { |
| 3753 |
var memo = Object.create(null); |
| 3754 |
var queues = Object.create(null); |
| 3755 |
hasher = hasher || identity; |
| 3756 |
var _fn = wrapAsync(fn); |
| 3757 |
var memoized = initialParams(function memoized(args, callback) { |
| 3758 |
var key = hasher.apply(null, args); |
| 3759 |
if (has(memo, key)) { |
| 3760 |
setImmediate$1(function() { |
| 3761 |
callback.apply(null, memo[key]); |
| 3762 |
}); |
| 3763 |
} else if (has(queues, key)) { |
| 3764 |
queues[key].push(callback); |
| 3765 |
} else { |
| 3766 |
queues[key] = [callback]; |
| 3767 |
_fn.apply(null, args.concat(function(/*args*/) { |
| 3768 |
var args = slice(arguments); |
| 3769 |
memo[key] = args; |
| 3770 |
var q = queues[key]; |
| 3771 |
delete queues[key]; |
| 3772 |
for (var i = 0, l = q.length; i < l; i++) { |
| 3773 |
q[i].apply(null, args); |
| 3774 |
} |
| 3775 |
})); |
| 3776 |
} |
| 3777 |
}); |
| 3778 |
memoized.memo = memo; |
| 3779 |
memoized.unmemoized = fn; |
| 3780 |
return memoized; |
| 3781 |
} |
| 3782 |
|
| 3783 |
/** |
| 3784 |
* Calls `callback` on a later loop around the event loop. In Node.js this just |
| 3785 |
* calls `setImmediate`. In the browser it will use `setImmediate` if |
| 3786 |
* available, otherwise `setTimeout(callback, 0)`, which means other higher |
| 3787 |
* priority events may precede the execution of `callback`. |
| 3788 |
* |
| 3789 |
* This is used internally for browser-compatibility purposes. |
| 3790 |
* |
| 3791 |
* @name nextTick |
| 3792 |
* @static |
| 3793 |
* @memberOf module:Utils |
| 3794 |
* @method |
| 3795 |
* @alias setImmediate |
| 3796 |
* @category Util |
| 3797 |
* @param {Function} callback - The function to call on a later loop around |
| 3798 |
* the event loop. Invoked with (args...). |
| 3799 |
* @param {...*} args... - any number of additional arguments to pass to the |
| 3800 |
* callback on the next tick. |
| 3801 |
* @example |
| 3802 |
* |
| 3803 |
* var call_order = []; |
| 3804 |
* async.nextTick(function() { |
| 3805 |
* call_order.push('two'); |
| 3806 |
* // call_order now equals ['one','two'] |
| 3807 |
* }); |
| 3808 |
* call_order.push('one'); |
| 3809 |
* |
| 3810 |
* async.setImmediate(function (a, b, c) { |
| 3811 |
* // a, b, and c equal 1, 2, and 3 |
| 3812 |
* }, 1, 2, 3); |
| 3813 |
*/ |
| 3814 |
var _defer$1; |
| 3815 |
|
| 3816 |
if (hasNextTick) { |
| 3817 |
_defer$1 = process.nextTick; |
| 3818 |
} else if (hasSetImmediate) { |
| 3819 |
_defer$1 = setImmediate; |
| 3820 |
} else { |
| 3821 |
_defer$1 = fallback; |
| 3822 |
} |
| 3823 |
|
| 3824 |
var nextTick = wrap(_defer$1); |
| 3825 |
|
| 3826 |
function _parallel(eachfn, tasks, callback) { |
| 3827 |
callback = callback || noop; |
| 3828 |
var results = isArrayLike(tasks) ? [] : {}; |
| 3829 |
|
| 3830 |
eachfn(tasks, function (task, key, callback) { |
| 3831 |
wrapAsync(task)(function (err, result) { |
| 3832 |
if (arguments.length > 2) { |
| 3833 |
result = slice(arguments, 1); |
| 3834 |
} |
| 3835 |
results[key] = result; |
| 3836 |
callback(err); |
| 3837 |
}); |
| 3838 |
}, function (err) { |
| 3839 |
callback(err, results); |
| 3840 |
}); |
| 3841 |
} |
| 3842 |
|
| 3843 |
/** |
| 3844 |
* Run the `tasks` collection of functions in parallel, without waiting until |
| 3845 |
* the previous function has completed. If any of the functions pass an error to |
| 3846 |
* its callback, the main `callback` is immediately called with the value of the |
| 3847 |
* error. Once the `tasks` have completed, the results are passed to the final |
| 3848 |
* `callback` as an array. |
| 3849 |
* |
| 3850 |
* **Note:** `parallel` is about kicking-off I/O tasks in parallel, not about |
| 3851 |
* parallel execution of code. If your tasks do not use any timers or perform |
| 3852 |
* any I/O, they will actually be executed in series. Any synchronous setup |
| 3853 |
* sections for each task will happen one after the other. JavaScript remains |
| 3854 |
* single-threaded. |
| 3855 |
* |
| 3856 |
* **Hint:** Use [`reflect`]{@link module:Utils.reflect} to continue the |
| 3857 |
* execution of other tasks when a task fails. |
| 3858 |
* |
| 3859 |
* It is also possible to use an object instead of an array. Each property will |
| 3860 |
* be run as a function and the results will be passed to the final `callback` |
| 3861 |
* as an object instead of an array. This can be a more readable way of handling |
| 3862 |
* results from {@link async.parallel}. |
| 3863 |
* |
| 3864 |
* @name parallel |
| 3865 |
* @static |
| 3866 |
* @memberOf module:ControlFlow |
| 3867 |
* @method |
| 3868 |
* @category Control Flow |
| 3869 |
* @param {Array|Iterable|Object} tasks - A collection of |
| 3870 |
* [async functions]{@link AsyncFunction} to run. |
| 3871 |
* Each async function can complete with any number of optional `result` values. |
| 3872 |
* @param {Function} [callback] - An optional callback to run once all the |
| 3873 |
* functions have completed successfully. This function gets a results array |
| 3874 |
* (or object) containing all the result arguments passed to the task callbacks. |
| 3875 |
* Invoked with (err, results). |
| 3876 |
* |
| 3877 |
* @example |
| 3878 |
* async.parallel([ |
| 3879 |
* function(callback) { |
| 3880 |
* setTimeout(function() { |
| 3881 |
* callback(null, 'one'); |
| 3882 |
* }, 200); |
| 3883 |
* }, |
| 3884 |
* function(callback) { |
| 3885 |
* setTimeout(function() { |
| 3886 |
* callback(null, 'two'); |
| 3887 |
* }, 100); |
| 3888 |
* } |
| 3889 |
* ], |
| 3890 |
* // optional callback |
| 3891 |
* function(err, results) { |
| 3892 |
* // the results array will equal ['one','two'] even though |
| 3893 |
* // the second function had a shorter timeout. |
| 3894 |
* }); |
| 3895 |
* |
| 3896 |
* // an example using an object instead of an array |
| 3897 |
* async.parallel({ |
| 3898 |
* one: function(callback) { |
| 3899 |
* setTimeout(function() { |
| 3900 |
* callback(null, 1); |
| 3901 |
* }, 200); |
| 3902 |
* }, |
| 3903 |
* two: function(callback) { |
| 3904 |
* setTimeout(function() { |
| 3905 |
* callback(null, 2); |
| 3906 |
* }, 100); |
| 3907 |
* } |
| 3908 |
* }, function(err, results) { |
| 3909 |
* // results is now equals to: {one: 1, two: 2} |
| 3910 |
* }); |
| 3911 |
*/ |
| 3912 |
function parallelLimit(tasks, callback) { |
| 3913 |
_parallel(eachOf, tasks, callback); |
| 3914 |
} |
| 3915 |
|
| 3916 |
/** |
| 3917 |
* The same as [`parallel`]{@link module:ControlFlow.parallel} but runs a maximum of `limit` async operations at a |
| 3918 |
* time. |
| 3919 |
* |
| 3920 |
* @name parallelLimit |
| 3921 |
* @static |
| 3922 |
* @memberOf module:ControlFlow |
| 3923 |
* @method |
| 3924 |
* @see [async.parallel]{@link module:ControlFlow.parallel} |
| 3925 |
* @category Control Flow |
| 3926 |
* @param {Array|Iterable|Object} tasks - A collection of |
| 3927 |
* [async functions]{@link AsyncFunction} to run. |
| 3928 |
* Each async function can complete with any number of optional `result` values. |
| 3929 |
* @param {number} limit - The maximum number of async operations at a time. |
| 3930 |
* @param {Function} [callback] - An optional callback to run once all the |
| 3931 |
* functions have completed successfully. This function gets a results array |
| 3932 |
* (or object) containing all the result arguments passed to the task callbacks. |
| 3933 |
* Invoked with (err, results). |
| 3934 |
*/ |
| 3935 |
function parallelLimit$1(tasks, limit, callback) { |
| 3936 |
_parallel(_eachOfLimit(limit), tasks, callback); |
| 3937 |
} |
| 3938 |
|
| 3939 |
/** |
| 3940 |
* A queue of tasks for the worker function to complete. |
| 3941 |
* @typedef {Object} QueueObject |
| 3942 |
* @memberOf module:ControlFlow |
| 3943 |
* @property {Function} length - a function returning the number of items |
| 3944 |
* waiting to be processed. Invoke with `queue.length()`. |
| 3945 |
* @property {boolean} started - a boolean indicating whether or not any |
| 3946 |
* items have been pushed and processed by the queue. |
| 3947 |
* @property {Function} running - a function returning the number of items |
| 3948 |
* currently being processed. Invoke with `queue.running()`. |
| 3949 |
* @property {Function} workersList - a function returning the array of items |
| 3950 |
* currently being processed. Invoke with `queue.workersList()`. |
| 3951 |
* @property {Function} idle - a function returning false if there are items |
| 3952 |
* waiting or being processed, or true if not. Invoke with `queue.idle()`. |
| 3953 |
* @property {number} concurrency - an integer for determining how many `worker` |
| 3954 |
* functions should be run in parallel. This property can be changed after a |
| 3955 |
* `queue` is created to alter the concurrency on-the-fly. |
| 3956 |
* @property {Function} push - add a new task to the `queue`. Calls `callback` |
| 3957 |
* once the `worker` has finished processing the task. Instead of a single task, |
| 3958 |
* a `tasks` array can be submitted. The respective callback is used for every |
| 3959 |
* task in the list. Invoke with `queue.push(task, [callback])`, |
| 3960 |
* @property {Function} unshift - add a new task to the front of the `queue`. |
| 3961 |
* Invoke with `queue.unshift(task, [callback])`. |
| 3962 |
* @property {Function} remove - remove items from the queue that match a test |
| 3963 |
* function. The test function will be passed an object with a `data` property, |
| 3964 |
* and a `priority` property, if this is a |
| 3965 |
* [priorityQueue]{@link module:ControlFlow.priorityQueue} object. |
| 3966 |
* Invoked with `queue.remove(testFn)`, where `testFn` is of the form |
| 3967 |
* `function ({data, priority}) {}` and returns a Boolean. |
| 3968 |
* @property {Function} saturated - a callback that is called when the number of |
| 3969 |
* running workers hits the `concurrency` limit, and further tasks will be |
| 3970 |
* queued. |
| 3971 |
* @property {Function} unsaturated - a callback that is called when the number |
| 3972 |
* of running workers is less than the `concurrency` & `buffer` limits, and |
| 3973 |
* further tasks will not be queued. |
| 3974 |
* @property {number} buffer - A minimum threshold buffer in order to say that |
| 3975 |
* the `queue` is `unsaturated`. |
| 3976 |
* @property {Function} empty - a callback that is called when the last item |
| 3977 |
* from the `queue` is given to a `worker`. |
| 3978 |
* @property {Function} drain - a callback that is called when the last item |
| 3979 |
* from the `queue` has returned from the `worker`. |
| 3980 |
* @property {Function} error - a callback that is called when a task errors. |
| 3981 |
* Has the signature `function(error, task)`. |
| 3982 |
* @property {boolean} paused - a boolean for determining whether the queue is |
| 3983 |
* in a paused state. |
| 3984 |
* @property {Function} pause - a function that pauses the processing of tasks |
| 3985 |
* until `resume()` is called. Invoke with `queue.pause()`. |
| 3986 |
* @property {Function} resume - a function that resumes the processing of |
| 3987 |
* queued tasks when the queue is paused. Invoke with `queue.resume()`. |
| 3988 |
* @property {Function} kill - a function that removes the `drain` callback and |
| 3989 |
* empties remaining tasks from the queue forcing it to go idle. Invoke with `queue.kill()`. |
| 3990 |
*/ |
| 3991 |
|
| 3992 |
/** |
| 3993 |
* Creates a `queue` object with the specified `concurrency`. Tasks added to the |
| 3994 |
* `queue` are processed in parallel (up to the `concurrency` limit). If all |
| 3995 |
* `worker`s are in progress, the task is queued until one becomes available. |
| 3996 |
* Once a `worker` completes a `task`, that `task`'s callback is called. |
| 3997 |
* |
| 3998 |
* @name queue |
| 3999 |
* @static |
| 4000 |
* @memberOf module:ControlFlow |
| 4001 |
* @method |
| 4002 |
* @category Control Flow |
| 4003 |
* @param {AsyncFunction} worker - An async function for processing a queued task. |
| 4004 |
* If you want to handle errors from an individual task, pass a callback to |
| 4005 |
* `q.push()`. Invoked with (task, callback). |
| 4006 |
* @param {number} [concurrency=1] - An `integer` for determining how many |
| 4007 |
* `worker` functions should be run in parallel. If omitted, the concurrency |
| 4008 |
* defaults to `1`. If the concurrency is `0`, an error is thrown. |
| 4009 |
* @returns {module:ControlFlow.QueueObject} A queue object to manage the tasks. Callbacks can |
| 4010 |
* attached as certain properties to listen for specific events during the |
| 4011 |
* lifecycle of the queue. |
| 4012 |
* @example |
| 4013 |
* |
| 4014 |
* // create a queue object with concurrency 2 |
| 4015 |
* var q = async.queue(function(task, callback) { |
| 4016 |
* console.log('hello ' + task.name); |
| 4017 |
* callback(); |
| 4018 |
* }, 2); |
| 4019 |
* |
| 4020 |
* // assign a callback |
| 4021 |
* q.drain = function() { |
| 4022 |
* console.log('all items have been processed'); |
| 4023 |
* }; |
| 4024 |
* |
| 4025 |
* // add some items to the queue |
| 4026 |
* q.push({name: 'foo'}, function(err) { |
| 4027 |
* console.log('finished processing foo'); |
| 4028 |
* }); |
| 4029 |
* q.push({name: 'bar'}, function (err) { |
| 4030 |
* console.log('finished processing bar'); |
| 4031 |
* }); |
| 4032 |
* |
| 4033 |
* // add some items to the queue (batch-wise) |
| 4034 |
* q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) { |
| 4035 |
* console.log('finished processing item'); |
| 4036 |
* }); |
| 4037 |
* |
| 4038 |
* // add some items to the front of the queue |
| 4039 |
* q.unshift({name: 'bar'}, function (err) { |
| 4040 |
* console.log('finished processing bar'); |
| 4041 |
* }); |
| 4042 |
*/ |
| 4043 |
var queue$1 = function (worker, concurrency) { |
| 4044 |
var _worker = wrapAsync(worker); |
| 4045 |
return queue(function (items, cb) { |
| 4046 |
_worker(items[0], cb); |
| 4047 |
}, concurrency, 1); |
| 4048 |
}; |
| 4049 |
|
| 4050 |
/** |
| 4051 |
* The same as [async.queue]{@link module:ControlFlow.queue} only tasks are assigned a priority and |
| 4052 |
* completed in ascending priority order. |
| 4053 |
* |
| 4054 |
* @name priorityQueue |
| 4055 |
* @static |
| 4056 |
* @memberOf module:ControlFlow |
| 4057 |
* @method |
| 4058 |
* @see [async.queue]{@link module:ControlFlow.queue} |
| 4059 |
* @category Control Flow |
| 4060 |
* @param {AsyncFunction} worker - An async function for processing a queued task. |
| 4061 |
* If you want to handle errors from an individual task, pass a callback to |
| 4062 |
* `q.push()`. |
| 4063 |
* Invoked with (task, callback). |
| 4064 |
* @param {number} concurrency - An `integer` for determining how many `worker` |
| 4065 |
* functions should be run in parallel. If omitted, the concurrency defaults to |
| 4066 |
* `1`. If the concurrency is `0`, an error is thrown. |
| 4067 |
* @returns {module:ControlFlow.QueueObject} A priorityQueue object to manage the tasks. There are two |
| 4068 |
* differences between `queue` and `priorityQueue` objects: |
| 4069 |
* * `push(task, priority, [callback])` - `priority` should be a number. If an |
| 4070 |
* array of `tasks` is given, all tasks will be assigned the same priority. |
| 4071 |
* * The `unshift` method was removed. |
| 4072 |
*/ |
| 4073 |
var priorityQueue = function(worker, concurrency) { |
| 4074 |
// Start with a normal queue |
| 4075 |
var q = queue$1(worker, concurrency); |
| 4076 |
|
| 4077 |
// Override push to accept second parameter representing priority |
| 4078 |
q.push = function(data, priority, callback) { |
| 4079 |
if (callback == null) callback = noop; |
| 4080 |
if (typeof callback !== 'function') { |
| 4081 |
throw new Error('task callback must be a function'); |
| 4082 |
} |
| 4083 |
q.started = true; |
| 4084 |
if (!isArray(data)) { |
| 4085 |
data = [data]; |
| 4086 |
} |
| 4087 |
if (data.length === 0) { |
| 4088 |
// call drain immediately if there are no tasks |
| 4089 |
return setImmediate$1(function() { |
| 4090 |
q.drain(); |
| 4091 |
}); |
| 4092 |
} |
| 4093 |
|
| 4094 |
priority = priority || 0; |
| 4095 |
var nextNode = q._tasks.head; |
| 4096 |
while (nextNode && priority >= nextNode.priority) { |
| 4097 |
nextNode = nextNode.next; |
| 4098 |
} |
| 4099 |
|
| 4100 |
for (var i = 0, l = data.length; i < l; i++) { |
| 4101 |
var item = { |
| 4102 |
data: data[i], |
| 4103 |
priority: priority, |
| 4104 |
callback: callback |
| 4105 |
}; |
| 4106 |
|
| 4107 |
if (nextNode) { |
| 4108 |
q._tasks.insertBefore(nextNode, item); |
| 4109 |
} else { |
| 4110 |
q._tasks.push(item); |
| 4111 |
} |
| 4112 |
} |
| 4113 |
setImmediate$1(q.process); |
| 4114 |
}; |
| 4115 |
|
| 4116 |
// Remove unshift function |
| 4117 |
delete q.unshift; |
| 4118 |
|
| 4119 |
return q; |
| 4120 |
}; |
| 4121 |
|
| 4122 |
/** |
| 4123 |
* Runs the `tasks` array of functions in parallel, without waiting until the |
| 4124 |
* previous function has completed. Once any of the `tasks` complete or pass an |
| 4125 |
* error to its callback, the main `callback` is immediately called. It's |
| 4126 |
* equivalent to `Promise.race()`. |
| 4127 |
* |
| 4128 |
* @name race |
| 4129 |
* @static |
| 4130 |
* @memberOf module:ControlFlow |
| 4131 |
* @method |
| 4132 |
* @category Control Flow |
| 4133 |
* @param {Array} tasks - An array containing [async functions]{@link AsyncFunction} |
| 4134 |
* to run. Each function can complete with an optional `result` value. |
| 4135 |
* @param {Function} callback - A callback to run once any of the functions have |
| 4136 |
* completed. This function gets an error or result from the first function that |
| 4137 |
* completed. Invoked with (err, result). |
| 4138 |
* @returns undefined |
| 4139 |
* @example |
| 4140 |
* |
| 4141 |
* async.race([ |
| 4142 |
* function(callback) { |
| 4143 |
* setTimeout(function() { |
| 4144 |
* callback(null, 'one'); |
| 4145 |
* }, 200); |
| 4146 |
* }, |
| 4147 |
* function(callback) { |
| 4148 |
* setTimeout(function() { |
| 4149 |
* callback(null, 'two'); |
| 4150 |
* }, 100); |
| 4151 |
* } |
| 4152 |
* ], |
| 4153 |
* // main callback |
| 4154 |
* function(err, result) { |
| 4155 |
* // the result will be equal to 'two' as it finishes earlier |
| 4156 |
* }); |
| 4157 |
*/ |
| 4158 |
function race(tasks, callback) { |
| 4159 |
callback = once(callback || noop); |
| 4160 |
if (!isArray(tasks)) return callback(new TypeError('First argument to race must be an array of functions')); |
| 4161 |
if (!tasks.length) return callback(); |
| 4162 |
for (var i = 0, l = tasks.length; i < l; i++) { |
| 4163 |
wrapAsync(tasks[i])(callback); |
| 4164 |
} |
| 4165 |
} |
| 4166 |
|
| 4167 |
/** |
| 4168 |
* Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order. |
| 4169 |
* |
| 4170 |
* @name reduceRight |
| 4171 |
* @static |
| 4172 |
* @memberOf module:Collections |
| 4173 |
* @method |
| 4174 |
* @see [async.reduce]{@link module:Collections.reduce} |
| 4175 |
* @alias foldr |
| 4176 |
* @category Collection |
| 4177 |
* @param {Array} array - A collection to iterate over. |
| 4178 |
* @param {*} memo - The initial state of the reduction. |
| 4179 |
* @param {AsyncFunction} iteratee - A function applied to each item in the |
| 4180 |
* array to produce the next step in the reduction. |
| 4181 |
* The `iteratee` should complete with the next state of the reduction. |
| 4182 |
* If the iteratee complete with an error, the reduction is stopped and the |
| 4183 |
* main `callback` is immediately called with the error. |
| 4184 |
* Invoked with (memo, item, callback). |
| 4185 |
* @param {Function} [callback] - A callback which is called after all the |
| 4186 |
* `iteratee` functions have finished. Result is the reduced value. Invoked with |
| 4187 |
* (err, result). |
| 4188 |
*/ |
| 4189 |
function reduceRight (array, memo, iteratee, callback) { |
| 4190 |
var reversed = slice(array).reverse(); |
| 4191 |
reduce(reversed, memo, iteratee, callback); |
| 4192 |
} |
| 4193 |
|
| 4194 |
/** |
| 4195 |
* Wraps the async function in another function that always completes with a |
| 4196 |
* result object, even when it errors. |
| 4197 |
* |
| 4198 |
* The result object has either the property `error` or `value`. |
| 4199 |
* |
| 4200 |
* @name reflect |
| 4201 |
* @static |
| 4202 |
* @memberOf module:Utils |
| 4203 |
* @method |
| 4204 |
* @category Util |
| 4205 |
* @param {AsyncFunction} fn - The async function you want to wrap |
| 4206 |
* @returns {Function} - A function that always passes null to it's callback as |
| 4207 |
* the error. The second argument to the callback will be an `object` with |
| 4208 |
* either an `error` or a `value` property. |
| 4209 |
* @example |
| 4210 |
* |
| 4211 |
* async.parallel([ |
| 4212 |
* async.reflect(function(callback) { |
| 4213 |
* // do some stuff ... |
| 4214 |
* callback(null, 'one'); |
| 4215 |
* }), |
| 4216 |
* async.reflect(function(callback) { |
| 4217 |
* // do some more stuff but error ... |
| 4218 |
* callback('bad stuff happened'); |
| 4219 |
* }), |
| 4220 |
* async.reflect(function(callback) { |
| 4221 |
* // do some more stuff ... |
| 4222 |
* callback(null, 'two'); |
| 4223 |
* }) |
| 4224 |
* ], |
| 4225 |
* // optional callback |
| 4226 |
* function(err, results) { |
| 4227 |
* // values |
| 4228 |
* // results[0].value = 'one' |
| 4229 |
* // results[1].error = 'bad stuff happened' |
| 4230 |
* // results[2].value = 'two' |
| 4231 |
* }); |
| 4232 |
*/ |
| 4233 |
function reflect(fn) { |
| 4234 |
var _fn = wrapAsync(fn); |
| 4235 |
return initialParams(function reflectOn(args, reflectCallback) { |
| 4236 |
args.push(function callback(error, cbArg) { |
| 4237 |
if (error) { |
| 4238 |
reflectCallback(null, { error: error }); |
| 4239 |
} else { |
| 4240 |
var value; |
| 4241 |
if (arguments.length <= 2) { |
| 4242 |
value = cbArg; |
| 4243 |
} else { |
| 4244 |
value = slice(arguments, 1); |
| 4245 |
} |
| 4246 |
reflectCallback(null, { value: value }); |
| 4247 |
} |
| 4248 |
}); |
| 4249 |
|
| 4250 |
return _fn.apply(this, args); |
| 4251 |
}); |
| 4252 |
} |
| 4253 |
|
| 4254 |
function reject$1(eachfn, arr, iteratee, callback) { |
| 4255 |
_filter(eachfn, arr, function(value, cb) { |
| 4256 |
iteratee(value, function(err, v) { |
| 4257 |
cb(err, !v); |
| 4258 |
}); |
| 4259 |
}, callback); |
| 4260 |
} |
| 4261 |
|
| 4262 |
/** |
| 4263 |
* The opposite of [`filter`]{@link module:Collections.filter}. Removes values that pass an `async` truth test. |
| 4264 |
* |
| 4265 |
* @name reject |
| 4266 |
* @static |
| 4267 |
* @memberOf module:Collections |
| 4268 |
* @method |
| 4269 |
* @see [async.filter]{@link module:Collections.filter} |
| 4270 |
* @category Collection |
| 4271 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 4272 |
* @param {Function} iteratee - An async truth test to apply to each item in |
| 4273 |
* `coll`. |
| 4274 |
* The should complete with a boolean value as its `result`. |
| 4275 |
* Invoked with (item, callback). |
| 4276 |
* @param {Function} [callback] - A callback which is called after all the |
| 4277 |
* `iteratee` functions have finished. Invoked with (err, results). |
| 4278 |
* @example |
| 4279 |
* |
| 4280 |
* async.reject(['file1','file2','file3'], function(filePath, callback) { |
| 4281 |
* fs.access(filePath, function(err) { |
| 4282 |
* callback(null, !err) |
| 4283 |
* }); |
| 4284 |
* }, function(err, results) { |
| 4285 |
* // results now equals an array of missing files |
| 4286 |
* createFiles(results); |
| 4287 |
* }); |
| 4288 |
*/ |
| 4289 |
var reject = doParallel(reject$1); |
| 4290 |
|
| 4291 |
/** |
| 4292 |
* A helper function that wraps an array or an object of functions with `reflect`. |
| 4293 |
* |
| 4294 |
* @name reflectAll |
| 4295 |
* @static |
| 4296 |
* @memberOf module:Utils |
| 4297 |
* @method |
| 4298 |
* @see [async.reflect]{@link module:Utils.reflect} |
| 4299 |
* @category Util |
| 4300 |
* @param {Array|Object|Iterable} tasks - The collection of |
| 4301 |
* [async functions]{@link AsyncFunction} to wrap in `async.reflect`. |
| 4302 |
* @returns {Array} Returns an array of async functions, each wrapped in |
| 4303 |
* `async.reflect` |
| 4304 |
* @example |
| 4305 |
* |
| 4306 |
* let tasks = [ |
| 4307 |
* function(callback) { |
| 4308 |
* setTimeout(function() { |
| 4309 |
* callback(null, 'one'); |
| 4310 |
* }, 200); |
| 4311 |
* }, |
| 4312 |
* function(callback) { |
| 4313 |
* // do some more stuff but error ... |
| 4314 |
* callback(new Error('bad stuff happened')); |
| 4315 |
* }, |
| 4316 |
* function(callback) { |
| 4317 |
* setTimeout(function() { |
| 4318 |
* callback(null, 'two'); |
| 4319 |
* }, 100); |
| 4320 |
* } |
| 4321 |
* ]; |
| 4322 |
* |
| 4323 |
* async.parallel(async.reflectAll(tasks), |
| 4324 |
* // optional callback |
| 4325 |
* function(err, results) { |
| 4326 |
* // values |
| 4327 |
* // results[0].value = 'one' |
| 4328 |
* // results[1].error = Error('bad stuff happened') |
| 4329 |
* // results[2].value = 'two' |
| 4330 |
* }); |
| 4331 |
* |
| 4332 |
* // an example using an object instead of an array |
| 4333 |
* let tasks = { |
| 4334 |
* one: function(callback) { |
| 4335 |
* setTimeout(function() { |
| 4336 |
* callback(null, 'one'); |
| 4337 |
* }, 200); |
| 4338 |
* }, |
| 4339 |
* two: function(callback) { |
| 4340 |
* callback('two'); |
| 4341 |
* }, |
| 4342 |
* three: function(callback) { |
| 4343 |
* setTimeout(function() { |
| 4344 |
* callback(null, 'three'); |
| 4345 |
* }, 100); |
| 4346 |
* } |
| 4347 |
* }; |
| 4348 |
* |
| 4349 |
* async.parallel(async.reflectAll(tasks), |
| 4350 |
* // optional callback |
| 4351 |
* function(err, results) { |
| 4352 |
* // values |
| 4353 |
* // results.one.value = 'one' |
| 4354 |
* // results.two.error = 'two' |
| 4355 |
* // results.three.value = 'three' |
| 4356 |
* }); |
| 4357 |
*/ |
| 4358 |
function reflectAll(tasks) { |
| 4359 |
var results; |
| 4360 |
if (isArray(tasks)) { |
| 4361 |
results = arrayMap(tasks, reflect); |
| 4362 |
} else { |
| 4363 |
results = {}; |
| 4364 |
baseForOwn(tasks, function(task, key) { |
| 4365 |
results[key] = reflect.call(this, task); |
| 4366 |
}); |
| 4367 |
} |
| 4368 |
return results; |
| 4369 |
} |
| 4370 |
|
| 4371 |
/** |
| 4372 |
* The same as [`reject`]{@link module:Collections.reject} but runs a maximum of `limit` async operations at a |
| 4373 |
* time. |
| 4374 |
* |
| 4375 |
* @name rejectLimit |
| 4376 |
* @static |
| 4377 |
* @memberOf module:Collections |
| 4378 |
* @method |
| 4379 |
* @see [async.reject]{@link module:Collections.reject} |
| 4380 |
* @category Collection |
| 4381 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 4382 |
* @param {number} limit - The maximum number of async operations at a time. |
| 4383 |
* @param {Function} iteratee - An async truth test to apply to each item in |
| 4384 |
* `coll`. |
| 4385 |
* The should complete with a boolean value as its `result`. |
| 4386 |
* Invoked with (item, callback). |
| 4387 |
* @param {Function} [callback] - A callback which is called after all the |
| 4388 |
* `iteratee` functions have finished. Invoked with (err, results). |
| 4389 |
*/ |
| 4390 |
var rejectLimit = doParallelLimit(reject$1); |
| 4391 |
|
| 4392 |
/** |
| 4393 |
* The same as [`reject`]{@link module:Collections.reject} but runs only a single async operation at a time. |
| 4394 |
* |
| 4395 |
* @name rejectSeries |
| 4396 |
* @static |
| 4397 |
* @memberOf module:Collections |
| 4398 |
* @method |
| 4399 |
* @see [async.reject]{@link module:Collections.reject} |
| 4400 |
* @category Collection |
| 4401 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 4402 |
* @param {Function} iteratee - An async truth test to apply to each item in |
| 4403 |
* `coll`. |
| 4404 |
* The should complete with a boolean value as its `result`. |
| 4405 |
* Invoked with (item, callback). |
| 4406 |
* @param {Function} [callback] - A callback which is called after all the |
| 4407 |
* `iteratee` functions have finished. Invoked with (err, results). |
| 4408 |
*/ |
| 4409 |
var rejectSeries = doLimit(rejectLimit, 1); |
| 4410 |
|
| 4411 |
/** |
| 4412 |
* Creates a function that returns `value`. |
| 4413 |
* |
| 4414 |
* @static |
| 4415 |
* @memberOf _ |
| 4416 |
* @since 2.4.0 |
| 4417 |
* @category Util |
| 4418 |
* @param {*} value The value to return from the new function. |
| 4419 |
* @returns {Function} Returns the new constant function. |
| 4420 |
* @example |
| 4421 |
* |
| 4422 |
* var objects = _.times(2, _.constant({ 'a': 1 })); |
| 4423 |
* |
| 4424 |
* console.log(objects); |
| 4425 |
* // => [{ 'a': 1 }, { 'a': 1 }] |
| 4426 |
* |
| 4427 |
* console.log(objects[0] === objects[1]); |
| 4428 |
* // => true |
| 4429 |
*/ |
| 4430 |
function constant$1(value) { |
| 4431 |
return function() { |
| 4432 |
return value; |
| 4433 |
}; |
| 4434 |
} |
| 4435 |
|
| 4436 |
/** |
| 4437 |
* Attempts to get a successful response from `task` no more than `times` times |
| 4438 |
* before returning an error. If the task is successful, the `callback` will be |
| 4439 |
* passed the result of the successful task. If all attempts fail, the callback |
| 4440 |
* will be passed the error and result (if any) of the final attempt. |
| 4441 |
* |
| 4442 |
* @name retry |
| 4443 |
* @static |
| 4444 |
* @memberOf module:ControlFlow |
| 4445 |
* @method |
| 4446 |
* @category Control Flow |
| 4447 |
* @see [async.retryable]{@link module:ControlFlow.retryable} |
| 4448 |
* @param {Object|number} [opts = {times: 5, interval: 0}| 5] - Can be either an |
| 4449 |
* object with `times` and `interval` or a number. |
| 4450 |
* * `times` - The number of attempts to make before giving up. The default |
| 4451 |
* is `5`. |
| 4452 |
* * `interval` - The time to wait between retries, in milliseconds. The |
| 4453 |
* default is `0`. The interval may also be specified as a function of the |
| 4454 |
* retry count (see example). |
| 4455 |
* * `errorFilter` - An optional synchronous function that is invoked on |
| 4456 |
* erroneous result. If it returns `true` the retry attempts will continue; |
| 4457 |
* if the function returns `false` the retry flow is aborted with the current |
| 4458 |
* attempt's error and result being returned to the final callback. |
| 4459 |
* Invoked with (err). |
| 4460 |
* * If `opts` is a number, the number specifies the number of times to retry, |
| 4461 |
* with the default interval of `0`. |
| 4462 |
* @param {AsyncFunction} task - An async function to retry. |
| 4463 |
* Invoked with (callback). |
| 4464 |
* @param {Function} [callback] - An optional callback which is called when the |
| 4465 |
* task has succeeded, or after the final failed attempt. It receives the `err` |
| 4466 |
* and `result` arguments of the last attempt at completing the `task`. Invoked |
| 4467 |
* with (err, results). |
| 4468 |
* |
| 4469 |
* @example |
| 4470 |
* |
| 4471 |
* // The `retry` function can be used as a stand-alone control flow by passing |
| 4472 |
* // a callback, as shown below: |
| 4473 |
* |
| 4474 |
* // try calling apiMethod 3 times |
| 4475 |
* async.retry(3, apiMethod, function(err, result) { |
| 4476 |
* // do something with the result |
| 4477 |
* }); |
| 4478 |
* |
| 4479 |
* // try calling apiMethod 3 times, waiting 200 ms between each retry |
| 4480 |
* async.retry({times: 3, interval: 200}, apiMethod, function(err, result) { |
| 4481 |
* // do something with the result |
| 4482 |
* }); |
| 4483 |
* |
| 4484 |
* // try calling apiMethod 10 times with exponential backoff |
| 4485 |
* // (i.e. intervals of 100, 200, 400, 800, 1600, ... milliseconds) |
| 4486 |
* async.retry({ |
| 4487 |
* times: 10, |
| 4488 |
* interval: function(retryCount) { |
| 4489 |
* return 50 * Math.pow(2, retryCount); |
| 4490 |
* } |
| 4491 |
* }, apiMethod, function(err, result) { |
| 4492 |
* // do something with the result |
| 4493 |
* }); |
| 4494 |
* |
| 4495 |
* // try calling apiMethod the default 5 times no delay between each retry |
| 4496 |
* async.retry(apiMethod, function(err, result) { |
| 4497 |
* // do something with the result |
| 4498 |
* }); |
| 4499 |
* |
| 4500 |
* // try calling apiMethod only when error condition satisfies, all other |
| 4501 |
* // errors will abort the retry control flow and return to final callback |
| 4502 |
* async.retry({ |
| 4503 |
* errorFilter: function(err) { |
| 4504 |
* return err.message === 'Temporary error'; // only retry on a specific error |
| 4505 |
* } |
| 4506 |
* }, apiMethod, function(err, result) { |
| 4507 |
* // do something with the result |
| 4508 |
* }); |
| 4509 |
* |
| 4510 |
* // It can also be embedded within other control flow functions to retry |
| 4511 |
* // individual methods that are not as reliable, like this: |
| 4512 |
* async.auto({ |
| 4513 |
* users: api.getUsers.bind(api), |
| 4514 |
* payments: async.retryable(3, api.getPayments.bind(api)) |
| 4515 |
* }, function(err, results) { |
| 4516 |
* // do something with the results |
| 4517 |
* }); |
| 4518 |
* |
| 4519 |
*/ |
| 4520 |
function retry(opts, task, callback) { |
| 4521 |
var DEFAULT_TIMES = 5; |
| 4522 |
var DEFAULT_INTERVAL = 0; |
| 4523 |
|
| 4524 |
var options = { |
| 4525 |
times: DEFAULT_TIMES, |
| 4526 |
intervalFunc: constant$1(DEFAULT_INTERVAL) |
| 4527 |
}; |
| 4528 |
|
| 4529 |
function parseTimes(acc, t) { |
| 4530 |
if (typeof t === 'object') { |
| 4531 |
acc.times = +t.times || DEFAULT_TIMES; |
| 4532 |
|
| 4533 |
acc.intervalFunc = typeof t.interval === 'function' ? |
| 4534 |
t.interval : |
| 4535 |
constant$1(+t.interval || DEFAULT_INTERVAL); |
| 4536 |
|
| 4537 |
acc.errorFilter = t.errorFilter; |
| 4538 |
} else if (typeof t === 'number' || typeof t === 'string') { |
| 4539 |
acc.times = +t || DEFAULT_TIMES; |
| 4540 |
} else { |
| 4541 |
throw new Error("Invalid arguments for async.retry"); |
| 4542 |
} |
| 4543 |
} |
| 4544 |
|
| 4545 |
if (arguments.length < 3 && typeof opts === 'function') { |
| 4546 |
callback = task || noop; |
| 4547 |
task = opts; |
| 4548 |
} else { |
| 4549 |
parseTimes(options, opts); |
| 4550 |
callback = callback || noop; |
| 4551 |
} |
| 4552 |
|
| 4553 |
if (typeof task !== 'function') { |
| 4554 |
throw new Error("Invalid arguments for async.retry"); |
| 4555 |
} |
| 4556 |
|
| 4557 |
var _task = wrapAsync(task); |
| 4558 |
|
| 4559 |
var attempt = 1; |
| 4560 |
function retryAttempt() { |
| 4561 |
_task(function(err) { |
| 4562 |
if (err && attempt++ < options.times && |
| 4563 |
(typeof options.errorFilter != 'function' || |
| 4564 |
options.errorFilter(err))) { |
| 4565 |
setTimeout(retryAttempt, options.intervalFunc(attempt)); |
| 4566 |
} else { |
| 4567 |
callback.apply(null, arguments); |
| 4568 |
} |
| 4569 |
}); |
| 4570 |
} |
| 4571 |
|
| 4572 |
retryAttempt(); |
| 4573 |
} |
| 4574 |
|
| 4575 |
/** |
| 4576 |
* A close relative of [`retry`]{@link module:ControlFlow.retry}. This method |
| 4577 |
* wraps a task and makes it retryable, rather than immediately calling it |
| 4578 |
* with retries. |
| 4579 |
* |
| 4580 |
* @name retryable |
| 4581 |
* @static |
| 4582 |
* @memberOf module:ControlFlow |
| 4583 |
* @method |
| 4584 |
* @see [async.retry]{@link module:ControlFlow.retry} |
| 4585 |
* @category Control Flow |
| 4586 |
* @param {Object|number} [opts = {times: 5, interval: 0}| 5] - optional |
| 4587 |
* options, exactly the same as from `retry` |
| 4588 |
* @param {AsyncFunction} task - the asynchronous function to wrap. |
| 4589 |
* This function will be passed any arguments passed to the returned wrapper. |
| 4590 |
* Invoked with (...args, callback). |
| 4591 |
* @returns {AsyncFunction} The wrapped function, which when invoked, will |
| 4592 |
* retry on an error, based on the parameters specified in `opts`. |
| 4593 |
* This function will accept the same parameters as `task`. |
| 4594 |
* @example |
| 4595 |
* |
| 4596 |
* async.auto({ |
| 4597 |
* dep1: async.retryable(3, getFromFlakyService), |
| 4598 |
* process: ["dep1", async.retryable(3, function (results, cb) { |
| 4599 |
* maybeProcessData(results.dep1, cb); |
| 4600 |
* })] |
| 4601 |
* }, callback); |
| 4602 |
*/ |
| 4603 |
var retryable = function (opts, task) { |
| 4604 |
if (!task) { |
| 4605 |
task = opts; |
| 4606 |
opts = null; |
| 4607 |
} |
| 4608 |
var _task = wrapAsync(task); |
| 4609 |
return initialParams(function (args, callback) { |
| 4610 |
function taskFn(cb) { |
| 4611 |
_task.apply(null, args.concat(cb)); |
| 4612 |
} |
| 4613 |
|
| 4614 |
if (opts) retry(opts, taskFn, callback); |
| 4615 |
else retry(taskFn, callback); |
| 4616 |
|
| 4617 |
}); |
| 4618 |
}; |
| 4619 |
|
| 4620 |
/** |
| 4621 |
* Run the functions in the `tasks` collection in series, each one running once |
| 4622 |
* the previous function has completed. If any functions in the series pass an |
| 4623 |
* error to its callback, no more functions are run, and `callback` is |
| 4624 |
* immediately called with the value of the error. Otherwise, `callback` |
| 4625 |
* receives an array of results when `tasks` have completed. |
| 4626 |
* |
| 4627 |
* It is also possible to use an object instead of an array. Each property will |
| 4628 |
* be run as a function, and the results will be passed to the final `callback` |
| 4629 |
* as an object instead of an array. This can be a more readable way of handling |
| 4630 |
* results from {@link async.series}. |
| 4631 |
* |
| 4632 |
* **Note** that while many implementations preserve the order of object |
| 4633 |
* properties, the [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) |
| 4634 |
* explicitly states that |
| 4635 |
* |
| 4636 |
* > The mechanics and order of enumerating the properties is not specified. |
| 4637 |
* |
| 4638 |
* So if you rely on the order in which your series of functions are executed, |
| 4639 |
* and want this to work on all platforms, consider using an array. |
| 4640 |
* |
| 4641 |
* @name series |
| 4642 |
* @static |
| 4643 |
* @memberOf module:ControlFlow |
| 4644 |
* @method |
| 4645 |
* @category Control Flow |
| 4646 |
* @param {Array|Iterable|Object} tasks - A collection containing |
| 4647 |
* [async functions]{@link AsyncFunction} to run in series. |
| 4648 |
* Each function can complete with any number of optional `result` values. |
| 4649 |
* @param {Function} [callback] - An optional callback to run once all the |
| 4650 |
* functions have completed. This function gets a results array (or object) |
| 4651 |
* containing all the result arguments passed to the `task` callbacks. Invoked |
| 4652 |
* with (err, result). |
| 4653 |
* @example |
| 4654 |
* async.series([ |
| 4655 |
* function(callback) { |
| 4656 |
* // do some stuff ... |
| 4657 |
* callback(null, 'one'); |
| 4658 |
* }, |
| 4659 |
* function(callback) { |
| 4660 |
* // do some more stuff ... |
| 4661 |
* callback(null, 'two'); |
| 4662 |
* } |
| 4663 |
* ], |
| 4664 |
* // optional callback |
| 4665 |
* function(err, results) { |
| 4666 |
* // results is now equal to ['one', 'two'] |
| 4667 |
* }); |
| 4668 |
* |
| 4669 |
* async.series({ |
| 4670 |
* one: function(callback) { |
| 4671 |
* setTimeout(function() { |
| 4672 |
* callback(null, 1); |
| 4673 |
* }, 200); |
| 4674 |
* }, |
| 4675 |
* two: function(callback){ |
| 4676 |
* setTimeout(function() { |
| 4677 |
* callback(null, 2); |
| 4678 |
* }, 100); |
| 4679 |
* } |
| 4680 |
* }, function(err, results) { |
| 4681 |
* // results is now equal to: {one: 1, two: 2} |
| 4682 |
* }); |
| 4683 |
*/ |
| 4684 |
function series(tasks, callback) { |
| 4685 |
_parallel(eachOfSeries, tasks, callback); |
| 4686 |
} |
| 4687 |
|
| 4688 |
/** |
| 4689 |
* Returns `true` if at least one element in the `coll` satisfies an async test. |
| 4690 |
* If any iteratee call returns `true`, the main `callback` is immediately |
| 4691 |
* called. |
| 4692 |
* |
| 4693 |
* @name some |
| 4694 |
* @static |
| 4695 |
* @memberOf module:Collections |
| 4696 |
* @method |
| 4697 |
* @alias any |
| 4698 |
* @category Collection |
| 4699 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 4700 |
* @param {AsyncFunction} iteratee - An async truth test to apply to each item |
| 4701 |
* in the collections in parallel. |
| 4702 |
* The iteratee should complete with a boolean `result` value. |
| 4703 |
* Invoked with (item, callback). |
| 4704 |
* @param {Function} [callback] - A callback which is called as soon as any |
| 4705 |
* iteratee returns `true`, or after all the iteratee functions have finished. |
| 4706 |
* Result will be either `true` or `false` depending on the values of the async |
| 4707 |
* tests. Invoked with (err, result). |
| 4708 |
* @example |
| 4709 |
* |
| 4710 |
* async.some(['file1','file2','file3'], function(filePath, callback) { |
| 4711 |
* fs.access(filePath, function(err) { |
| 4712 |
* callback(null, !err) |
| 4713 |
* }); |
| 4714 |
* }, function(err, result) { |
| 4715 |
* // if result is true then at least one of the files exists |
| 4716 |
* }); |
| 4717 |
*/ |
| 4718 |
var some = doParallel(_createTester(Boolean, identity)); |
| 4719 |
|
| 4720 |
/** |
| 4721 |
* The same as [`some`]{@link module:Collections.some} but runs a maximum of `limit` async operations at a time. |
| 4722 |
* |
| 4723 |
* @name someLimit |
| 4724 |
* @static |
| 4725 |
* @memberOf module:Collections |
| 4726 |
* @method |
| 4727 |
* @see [async.some]{@link module:Collections.some} |
| 4728 |
* @alias anyLimit |
| 4729 |
* @category Collection |
| 4730 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 4731 |
* @param {number} limit - The maximum number of async operations at a time. |
| 4732 |
* @param {AsyncFunction} iteratee - An async truth test to apply to each item |
| 4733 |
* in the collections in parallel. |
| 4734 |
* The iteratee should complete with a boolean `result` value. |
| 4735 |
* Invoked with (item, callback). |
| 4736 |
* @param {Function} [callback] - A callback which is called as soon as any |
| 4737 |
* iteratee returns `true`, or after all the iteratee functions have finished. |
| 4738 |
* Result will be either `true` or `false` depending on the values of the async |
| 4739 |
* tests. Invoked with (err, result). |
| 4740 |
*/ |
| 4741 |
var someLimit = doParallelLimit(_createTester(Boolean, identity)); |
| 4742 |
|
| 4743 |
/** |
| 4744 |
* The same as [`some`]{@link module:Collections.some} but runs only a single async operation at a time. |
| 4745 |
* |
| 4746 |
* @name someSeries |
| 4747 |
* @static |
| 4748 |
* @memberOf module:Collections |
| 4749 |
* @method |
| 4750 |
* @see [async.some]{@link module:Collections.some} |
| 4751 |
* @alias anySeries |
| 4752 |
* @category Collection |
| 4753 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 4754 |
* @param {AsyncFunction} iteratee - An async truth test to apply to each item |
| 4755 |
* in the collections in series. |
| 4756 |
* The iteratee should complete with a boolean `result` value. |
| 4757 |
* Invoked with (item, callback). |
| 4758 |
* @param {Function} [callback] - A callback which is called as soon as any |
| 4759 |
* iteratee returns `true`, or after all the iteratee functions have finished. |
| 4760 |
* Result will be either `true` or `false` depending on the values of the async |
| 4761 |
* tests. Invoked with (err, result). |
| 4762 |
*/ |
| 4763 |
var someSeries = doLimit(someLimit, 1); |
| 4764 |
|
| 4765 |
/** |
| 4766 |
* Sorts a list by the results of running each `coll` value through an async |
| 4767 |
* `iteratee`. |
| 4768 |
* |
| 4769 |
* @name sortBy |
| 4770 |
* @static |
| 4771 |
* @memberOf module:Collections |
| 4772 |
* @method |
| 4773 |
* @category Collection |
| 4774 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 4775 |
* @param {AsyncFunction} iteratee - An async function to apply to each item in |
| 4776 |
* `coll`. |
| 4777 |
* The iteratee should complete with a value to use as the sort criteria as |
| 4778 |
* its `result`. |
| 4779 |
* Invoked with (item, callback). |
| 4780 |
* @param {Function} callback - A callback which is called after all the |
| 4781 |
* `iteratee` functions have finished, or an error occurs. Results is the items |
| 4782 |
* from the original `coll` sorted by the values returned by the `iteratee` |
| 4783 |
* calls. Invoked with (err, results). |
| 4784 |
* @example |
| 4785 |
* |
| 4786 |
* async.sortBy(['file1','file2','file3'], function(file, callback) { |
| 4787 |
* fs.stat(file, function(err, stats) { |
| 4788 |
* callback(err, stats.mtime); |
| 4789 |
* }); |
| 4790 |
* }, function(err, results) { |
| 4791 |
* // results is now the original array of files sorted by |
| 4792 |
* // modified date |
| 4793 |
* }); |
| 4794 |
* |
| 4795 |
* // By modifying the callback parameter the |
| 4796 |
* // sorting order can be influenced: |
| 4797 |
* |
| 4798 |
* // ascending order |
| 4799 |
* async.sortBy([1,9,3,5], function(x, callback) { |
| 4800 |
* callback(null, x); |
| 4801 |
* }, function(err,result) { |
| 4802 |
* // result callback |
| 4803 |
* }); |
| 4804 |
* |
| 4805 |
* // descending order |
| 4806 |
* async.sortBy([1,9,3,5], function(x, callback) { |
| 4807 |
* callback(null, x*-1); //<- x*-1 instead of x, turns the order around |
| 4808 |
* }, function(err,result) { |
| 4809 |
* // result callback |
| 4810 |
* }); |
| 4811 |
*/ |
| 4812 |
function sortBy (coll, iteratee, callback) { |
| 4813 |
var _iteratee = wrapAsync(iteratee); |
| 4814 |
map(coll, function (x, callback) { |
| 4815 |
_iteratee(x, function (err, criteria) { |
| 4816 |
if (err) return callback(err); |
| 4817 |
callback(null, {value: x, criteria: criteria}); |
| 4818 |
}); |
| 4819 |
}, function (err, results) { |
| 4820 |
if (err) return callback(err); |
| 4821 |
callback(null, arrayMap(results.sort(comparator), baseProperty('value'))); |
| 4822 |
}); |
| 4823 |
|
| 4824 |
function comparator(left, right) { |
| 4825 |
var a = left.criteria, b = right.criteria; |
| 4826 |
return a < b ? -1 : a > b ? 1 : 0; |
| 4827 |
} |
| 4828 |
} |
| 4829 |
|
| 4830 |
/** |
| 4831 |
* Sets a time limit on an asynchronous function. If the function does not call |
| 4832 |
* its callback within the specified milliseconds, it will be called with a |
| 4833 |
* timeout error. The code property for the error object will be `'ETIMEDOUT'`. |
| 4834 |
* |
| 4835 |
* @name timeout |
| 4836 |
* @static |
| 4837 |
* @memberOf module:Utils |
| 4838 |
* @method |
| 4839 |
* @category Util |
| 4840 |
* @param {AsyncFunction} asyncFn - The async function to limit in time. |
| 4841 |
* @param {number} milliseconds - The specified time limit. |
| 4842 |
* @param {*} [info] - Any variable you want attached (`string`, `object`, etc) |
| 4843 |
* to timeout Error for more information.. |
| 4844 |
* @returns {AsyncFunction} Returns a wrapped function that can be used with any |
| 4845 |
* of the control flow functions. |
| 4846 |
* Invoke this function with the same parameters as you would `asyncFunc`. |
| 4847 |
* @example |
| 4848 |
* |
| 4849 |
* function myFunction(foo, callback) { |
| 4850 |
* doAsyncTask(foo, function(err, data) { |
| 4851 |
* // handle errors |
| 4852 |
* if (err) return callback(err); |
| 4853 |
* |
| 4854 |
* // do some stuff ... |
| 4855 |
* |
| 4856 |
* // return processed data |
| 4857 |
* return callback(null, data); |
| 4858 |
* }); |
| 4859 |
* } |
| 4860 |
* |
| 4861 |
* var wrapped = async.timeout(myFunction, 1000); |
| 4862 |
* |
| 4863 |
* // call `wrapped` as you would `myFunction` |
| 4864 |
* wrapped({ bar: 'bar' }, function(err, data) { |
| 4865 |
* // if `myFunction` takes < 1000 ms to execute, `err` |
| 4866 |
* // and `data` will have their expected values |
| 4867 |
* |
| 4868 |
* // else `err` will be an Error with the code 'ETIMEDOUT' |
| 4869 |
* }); |
| 4870 |
*/ |
| 4871 |
function timeout(asyncFn, milliseconds, info) { |
| 4872 |
var fn = wrapAsync(asyncFn); |
| 4873 |
|
| 4874 |
return initialParams(function (args, callback) { |
| 4875 |
var timedOut = false; |
| 4876 |
var timer; |
| 4877 |
|
| 4878 |
function timeoutCallback() { |
| 4879 |
var name = asyncFn.name || 'anonymous'; |
| 4880 |
var error = new Error('Callback function "' + name + '" timed out.'); |
| 4881 |
error.code = 'ETIMEDOUT'; |
| 4882 |
if (info) { |
| 4883 |
error.info = info; |
| 4884 |
} |
| 4885 |
timedOut = true; |
| 4886 |
callback(error); |
| 4887 |
} |
| 4888 |
|
| 4889 |
args.push(function () { |
| 4890 |
if (!timedOut) { |
| 4891 |
callback.apply(null, arguments); |
| 4892 |
clearTimeout(timer); |
| 4893 |
} |
| 4894 |
}); |
| 4895 |
|
| 4896 |
// setup timer and call original function |
| 4897 |
timer = setTimeout(timeoutCallback, milliseconds); |
| 4898 |
fn.apply(null, args); |
| 4899 |
}); |
| 4900 |
} |
| 4901 |
|
| 4902 |
/* Built-in method references for those with the same name as other `lodash` methods. */ |
| 4903 |
var nativeCeil = Math.ceil; |
| 4904 |
var nativeMax = Math.max; |
| 4905 |
|
| 4906 |
/** |
| 4907 |
* The base implementation of `_.range` and `_.rangeRight` which doesn't |
| 4908 |
* coerce arguments. |
| 4909 |
* |
| 4910 |
* @private |
| 4911 |
* @param {number} start The start of the range. |
| 4912 |
* @param {number} end The end of the range. |
| 4913 |
* @param {number} step The value to increment or decrement by. |
| 4914 |
* @param {boolean} [fromRight] Specify iterating from right to left. |
| 4915 |
* @returns {Array} Returns the range of numbers. |
| 4916 |
*/ |
| 4917 |
function baseRange(start, end, step, fromRight) { |
| 4918 |
var index = -1, |
| 4919 |
length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), |
| 4920 |
result = Array(length); |
| 4921 |
|
| 4922 |
while (length--) { |
| 4923 |
result[fromRight ? length : ++index] = start; |
| 4924 |
start += step; |
| 4925 |
} |
| 4926 |
return result; |
| 4927 |
} |
| 4928 |
|
| 4929 |
/** |
| 4930 |
* The same as [times]{@link module:ControlFlow.times} but runs a maximum of `limit` async operations at a |
| 4931 |
* time. |
| 4932 |
* |
| 4933 |
* @name timesLimit |
| 4934 |
* @static |
| 4935 |
* @memberOf module:ControlFlow |
| 4936 |
* @method |
| 4937 |
* @see [async.times]{@link module:ControlFlow.times} |
| 4938 |
* @category Control Flow |
| 4939 |
* @param {number} count - The number of times to run the function. |
| 4940 |
* @param {number} limit - The maximum number of async operations at a time. |
| 4941 |
* @param {AsyncFunction} iteratee - The async function to call `n` times. |
| 4942 |
* Invoked with the iteration index and a callback: (n, next). |
| 4943 |
* @param {Function} callback - see [async.map]{@link module:Collections.map}. |
| 4944 |
*/ |
| 4945 |
function timeLimit(count, limit, iteratee, callback) { |
| 4946 |
var _iteratee = wrapAsync(iteratee); |
| 4947 |
mapLimit(baseRange(0, count, 1), limit, _iteratee, callback); |
| 4948 |
} |
| 4949 |
|
| 4950 |
/** |
| 4951 |
* Calls the `iteratee` function `n` times, and accumulates results in the same |
| 4952 |
* manner you would use with [map]{@link module:Collections.map}. |
| 4953 |
* |
| 4954 |
* @name times |
| 4955 |
* @static |
| 4956 |
* @memberOf module:ControlFlow |
| 4957 |
* @method |
| 4958 |
* @see [async.map]{@link module:Collections.map} |
| 4959 |
* @category Control Flow |
| 4960 |
* @param {number} n - The number of times to run the function. |
| 4961 |
* @param {AsyncFunction} iteratee - The async function to call `n` times. |
| 4962 |
* Invoked with the iteration index and a callback: (n, next). |
| 4963 |
* @param {Function} callback - see {@link module:Collections.map}. |
| 4964 |
* @example |
| 4965 |
* |
| 4966 |
* // Pretend this is some complicated async factory |
| 4967 |
* var createUser = function(id, callback) { |
| 4968 |
* callback(null, { |
| 4969 |
* id: 'user' + id |
| 4970 |
* }); |
| 4971 |
* }; |
| 4972 |
* |
| 4973 |
* // generate 5 users |
| 4974 |
* async.times(5, function(n, next) { |
| 4975 |
* createUser(n, function(err, user) { |
| 4976 |
* next(err, user); |
| 4977 |
* }); |
| 4978 |
* }, function(err, users) { |
| 4979 |
* // we should now have 5 users |
| 4980 |
* }); |
| 4981 |
*/ |
| 4982 |
var times = doLimit(timeLimit, Infinity); |
| 4983 |
|
| 4984 |
/** |
| 4985 |
* The same as [times]{@link module:ControlFlow.times} but runs only a single async operation at a time. |
| 4986 |
* |
| 4987 |
* @name timesSeries |
| 4988 |
* @static |
| 4989 |
* @memberOf module:ControlFlow |
| 4990 |
* @method |
| 4991 |
* @see [async.times]{@link module:ControlFlow.times} |
| 4992 |
* @category Control Flow |
| 4993 |
* @param {number} n - The number of times to run the function. |
| 4994 |
* @param {AsyncFunction} iteratee - The async function to call `n` times. |
| 4995 |
* Invoked with the iteration index and a callback: (n, next). |
| 4996 |
* @param {Function} callback - see {@link module:Collections.map}. |
| 4997 |
*/ |
| 4998 |
var timesSeries = doLimit(timeLimit, 1); |
| 4999 |
|
| 5000 |
/** |
| 5001 |
* A relative of `reduce`. Takes an Object or Array, and iterates over each |
| 5002 |
* element in series, each step potentially mutating an `accumulator` value. |
| 5003 |
* The type of the accumulator defaults to the type of collection passed in. |
| 5004 |
* |
| 5005 |
* @name transform |
| 5006 |
* @static |
| 5007 |
* @memberOf module:Collections |
| 5008 |
* @method |
| 5009 |
* @category Collection |
| 5010 |
* @param {Array|Iterable|Object} coll - A collection to iterate over. |
| 5011 |
* @param {*} [accumulator] - The initial state of the transform. If omitted, |
| 5012 |
* it will default to an empty Object or Array, depending on the type of `coll` |
| 5013 |
* @param {AsyncFunction} iteratee - A function applied to each item in the |
| 5014 |
* collection that potentially modifies the accumulator. |
| 5015 |
* Invoked with (accumulator, item, key, callback). |
| 5016 |
* @param {Function} [callback] - A callback which is called after all the |
| 5017 |
* `iteratee` functions have finished. Result is the transformed accumulator. |
| 5018 |
* Invoked with (err, result). |
| 5019 |
* @example |
| 5020 |
* |
| 5021 |
* async.transform([1,2,3], function(acc, item, index, callback) { |
| 5022 |
* // pointless async: |
| 5023 |
* process.nextTick(function() { |
| 5024 |
* acc.push(item * 2) |
| 5025 |
* callback(null) |
| 5026 |
* }); |
| 5027 |
* }, function(err, result) { |
| 5028 |
* // result is now equal to [2, 4, 6] |
| 5029 |
* }); |
| 5030 |
* |
| 5031 |
* @example |
| 5032 |
* |
| 5033 |
* async.transform({a: 1, b: 2, c: 3}, function (obj, val, key, callback) { |
| 5034 |
* setImmediate(function () { |
| 5035 |
* obj[key] = val * 2; |
| 5036 |
* callback(); |
| 5037 |
* }) |
| 5038 |
* }, function (err, result) { |
| 5039 |
* // result is equal to {a: 2, b: 4, c: 6} |
| 5040 |
* }) |
| 5041 |
*/ |
| 5042 |
function transform (coll, accumulator, iteratee, callback) { |
| 5043 |
if (arguments.length <= 3) { |
| 5044 |
callback = iteratee; |
| 5045 |
iteratee = accumulator; |
| 5046 |
accumulator = isArray(coll) ? [] : {}; |
| 5047 |
} |
| 5048 |
callback = once(callback || noop); |
| 5049 |
var _iteratee = wrapAsync(iteratee); |
| 5050 |
|
| 5051 |
eachOf(coll, function(v, k, cb) { |
| 5052 |
_iteratee(accumulator, v, k, cb); |
| 5053 |
}, function(err) { |
| 5054 |
callback(err, accumulator); |
| 5055 |
}); |
| 5056 |
} |
| 5057 |
|
| 5058 |
/** |
| 5059 |
* It runs each task in series but stops whenever any of the functions were |
| 5060 |
* successful. If one of the tasks were successful, the `callback` will be |
| 5061 |
* passed the result of the successful task. If all tasks fail, the callback |
| 5062 |
* will be passed the error and result (if any) of the final attempt. |
| 5063 |
* |
| 5064 |
* @name tryEach |
| 5065 |
* @static |
| 5066 |
* @memberOf module:ControlFlow |
| 5067 |
* @method |
| 5068 |
* @category Control Flow |
| 5069 |
* @param {Array|Iterable|Object} tasks - A collection containing functions to |
| 5070 |
* run, each function is passed a `callback(err, result)` it must call on |
| 5071 |
* completion with an error `err` (which can be `null`) and an optional `result` |
| 5072 |
* value. |
| 5073 |
* @param {Function} [callback] - An optional callback which is called when one |
| 5074 |
* of the tasks has succeeded, or all have failed. It receives the `err` and |
| 5075 |
* `result` arguments of the last attempt at completing the `task`. Invoked with |
| 5076 |
* (err, results). |
| 5077 |
* @example |
| 5078 |
* async.try([ |
| 5079 |
* function getDataFromFirstWebsite(callback) { |
| 5080 |
* // Try getting the data from the first website |
| 5081 |
* callback(err, data); |
| 5082 |
* }, |
| 5083 |
* function getDataFromSecondWebsite(callback) { |
| 5084 |
* // First website failed, |
| 5085 |
* // Try getting the data from the backup website |
| 5086 |
* callback(err, data); |
| 5087 |
* } |
| 5088 |
* ], |
| 5089 |
* // optional callback |
| 5090 |
* function(err, results) { |
| 5091 |
* Now do something with the data. |
| 5092 |
* }); |
| 5093 |
* |
| 5094 |
*/ |
| 5095 |
function tryEach(tasks, callback) { |
| 5096 |
var error = null; |
| 5097 |
var result; |
| 5098 |
callback = callback || noop; |
| 5099 |
eachSeries(tasks, function(task, callback) { |
| 5100 |
wrapAsync(task)(function (err, res/*, ...args*/) { |
| 5101 |
if (arguments.length > 2) { |
| 5102 |
result = slice(arguments, 1); |
| 5103 |
} else { |
| 5104 |
result = res; |
| 5105 |
} |
| 5106 |
error = err; |
| 5107 |
callback(!err); |
| 5108 |
}); |
| 5109 |
}, function () { |
| 5110 |
callback(error, result); |
| 5111 |
}); |
| 5112 |
} |
| 5113 |
|
| 5114 |
/** |
| 5115 |
* Undoes a [memoize]{@link module:Utils.memoize}d function, reverting it to the original, |
| 5116 |
* unmemoized form. Handy for testing. |
| 5117 |
* |
| 5118 |
* @name unmemoize |
| 5119 |
* @static |
| 5120 |
* @memberOf module:Utils |
| 5121 |
* @method |
| 5122 |
* @see [async.memoize]{@link module:Utils.memoize} |
| 5123 |
* @category Util |
| 5124 |
* @param {AsyncFunction} fn - the memoized function |
| 5125 |
* @returns {AsyncFunction} a function that calls the original unmemoized function |
| 5126 |
*/ |
| 5127 |
function unmemoize(fn) { |
| 5128 |
return function () { |
| 5129 |
return (fn.unmemoized || fn).apply(null, arguments); |
| 5130 |
}; |
| 5131 |
} |
| 5132 |
|
| 5133 |
/** |
| 5134 |
* Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when |
| 5135 |
* stopped, or an error occurs. |
| 5136 |
* |
| 5137 |
* @name whilst |
| 5138 |
* @static |
| 5139 |
* @memberOf module:ControlFlow |
| 5140 |
* @method |
| 5141 |
* @category Control Flow |
| 5142 |
* @param {Function} test - synchronous truth test to perform before each |
| 5143 |
* execution of `iteratee`. Invoked with (). |
| 5144 |
* @param {AsyncFunction} iteratee - An async function which is called each time |
| 5145 |
* `test` passes. Invoked with (callback). |
| 5146 |
* @param {Function} [callback] - A callback which is called after the test |
| 5147 |
* function has failed and repeated execution of `iteratee` has stopped. `callback` |
| 5148 |
* will be passed an error and any arguments passed to the final `iteratee`'s |
| 5149 |
* callback. Invoked with (err, [results]); |
| 5150 |
* @returns undefined |
| 5151 |
* @example |
| 5152 |
* |
| 5153 |
* var count = 0; |
| 5154 |
* async.whilst( |
| 5155 |
* function() { return count < 5; }, |
| 5156 |
* function(callback) { |
| 5157 |
* count++; |
| 5158 |
* setTimeout(function() { |
| 5159 |
* callback(null, count); |
| 5160 |
* }, 1000); |
| 5161 |
* }, |
| 5162 |
* function (err, n) { |
| 5163 |
* // 5 seconds have passed, n = 5 |
| 5164 |
* } |
| 5165 |
* ); |
| 5166 |
*/ |
| 5167 |
function whilst(test, iteratee, callback) { |
| 5168 |
callback = onlyOnce(callback || noop); |
| 5169 |
var _iteratee = wrapAsync(iteratee); |
| 5170 |
if (!test()) return callback(null); |
| 5171 |
var next = function(err/*, ...args*/) { |
| 5172 |
if (err) return callback(err); |
| 5173 |
if (test()) return _iteratee(next); |
| 5174 |
var args = slice(arguments, 1); |
| 5175 |
callback.apply(null, [null].concat(args)); |
| 5176 |
}; |
| 5177 |
_iteratee(next); |
| 5178 |
} |
| 5179 |
|
| 5180 |
/** |
| 5181 |
* Repeatedly call `iteratee` until `test` returns `true`. Calls `callback` when |
| 5182 |
* stopped, or an error occurs. `callback` will be passed an error and any |
| 5183 |
* arguments passed to the final `iteratee`'s callback. |
| 5184 |
* |
| 5185 |
* The inverse of [whilst]{@link module:ControlFlow.whilst}. |
| 5186 |
* |
| 5187 |
* @name until |
| 5188 |
* @static |
| 5189 |
* @memberOf module:ControlFlow |
| 5190 |
* @method |
| 5191 |
* @see [async.whilst]{@link module:ControlFlow.whilst} |
| 5192 |
* @category Control Flow |
| 5193 |
* @param {Function} test - synchronous truth test to perform before each |
| 5194 |
* execution of `iteratee`. Invoked with (). |
| 5195 |
* @param {AsyncFunction} iteratee - An async function which is called each time |
| 5196 |
* `test` fails. Invoked with (callback). |
| 5197 |
* @param {Function} [callback] - A callback which is called after the test |
| 5198 |
* function has passed and repeated execution of `iteratee` has stopped. `callback` |
| 5199 |
* will be passed an error and any arguments passed to the final `iteratee`'s |
| 5200 |
* callback. Invoked with (err, [results]); |
| 5201 |
*/ |
| 5202 |
function until(test, iteratee, callback) { |
| 5203 |
whilst(function() { |
| 5204 |
return !test.apply(this, arguments); |
| 5205 |
}, iteratee, callback); |
| 5206 |
} |
| 5207 |
|
| 5208 |
/** |
| 5209 |
* Runs the `tasks` array of functions in series, each passing their results to |
| 5210 |
* the next in the array. However, if any of the `tasks` pass an error to their |
| 5211 |
* own callback, the next function is not executed, and the main `callback` is |
| 5212 |
* immediately called with the error. |
| 5213 |
* |
| 5214 |
* @name waterfall |
| 5215 |
* @static |
| 5216 |
* @memberOf module:ControlFlow |
| 5217 |
* @method |
| 5218 |
* @category Control Flow |
| 5219 |
* @param {Array} tasks - An array of [async functions]{@link AsyncFunction} |
| 5220 |
* to run. |
| 5221 |
* Each function should complete with any number of `result` values. |
| 5222 |
* The `result` values will be passed as arguments, in order, to the next task. |
| 5223 |
* @param {Function} [callback] - An optional callback to run once all the |
| 5224 |
* functions have completed. This will be passed the results of the last task's |
| 5225 |
* callback. Invoked with (err, [results]). |
| 5226 |
* @returns undefined |
| 5227 |
* @example |
| 5228 |
* |
| 5229 |
* async.waterfall([ |
| 5230 |
* function(callback) { |
| 5231 |
* callback(null, 'one', 'two'); |
| 5232 |
* }, |
| 5233 |
* function(arg1, arg2, callback) { |
| 5234 |
* // arg1 now equals 'one' and arg2 now equals 'two' |
| 5235 |
* callback(null, 'three'); |
| 5236 |
* }, |
| 5237 |
* function(arg1, callback) { |
| 5238 |
* // arg1 now equals 'three' |
| 5239 |
* callback(null, 'done'); |
| 5240 |
* } |
| 5241 |
* ], function (err, result) { |
| 5242 |
* // result now equals 'done' |
| 5243 |
* }); |
| 5244 |
* |
| 5245 |
* // Or, with named functions: |
| 5246 |
* async.waterfall([ |
| 5247 |
* myFirstFunction, |
| 5248 |
* mySecondFunction, |
| 5249 |
* myLastFunction, |
| 5250 |
* ], function (err, result) { |
| 5251 |
* // result now equals 'done' |
| 5252 |
* }); |
| 5253 |
* function myFirstFunction(callback) { |
| 5254 |
* callback(null, 'one', 'two'); |
| 5255 |
* } |
| 5256 |
* function mySecondFunction(arg1, arg2, callback) { |
| 5257 |
* // arg1 now equals 'one' and arg2 now equals 'two' |
| 5258 |
* callback(null, 'three'); |
| 5259 |
* } |
| 5260 |
* function myLastFunction(arg1, callback) { |
| 5261 |
* // arg1 now equals 'three' |
| 5262 |
* callback(null, 'done'); |
| 5263 |
* } |
| 5264 |
*/ |
| 5265 |
var waterfall = function(tasks, callback) { |
| 5266 |
callback = once(callback || noop); |
| 5267 |
if (!isArray(tasks)) return callback(new Error('First argument to waterfall must be an array of functions')); |
| 5268 |
if (!tasks.length) return callback(); |
| 5269 |
var taskIndex = 0; |
| 5270 |
|
| 5271 |
function nextTask(args) { |
| 5272 |
var task = wrapAsync(tasks[taskIndex++]); |
| 5273 |
args.push(onlyOnce(next)); |
| 5274 |
task.apply(null, args); |
| 5275 |
} |
| 5276 |
|
| 5277 |
function next(err/*, ...args*/) { |
| 5278 |
if (err || taskIndex === tasks.length) { |
| 5279 |
return callback.apply(null, arguments); |
| 5280 |
} |
| 5281 |
nextTask(slice(arguments, 1)); |
| 5282 |
} |
| 5283 |
|
| 5284 |
nextTask([]); |
| 5285 |
}; |
| 5286 |
|
| 5287 |
/** |
| 5288 |
* An "async function" in the context of Async is an asynchronous function with |
| 5289 |
* a variable number of parameters, with the final parameter being a callback. |
| 5290 |
* (`function (arg1, arg2, ..., callback) {}`) |
| 5291 |
* The final callback is of the form `callback(err, results...)`, which must be |
| 5292 |
* called once the function is completed. The callback should be called with a |
| 5293 |
* Error as its first argument to signal that an error occurred. |
| 5294 |
* Otherwise, if no error occurred, it should be called with `null` as the first |
| 5295 |
* argument, and any additional `result` arguments that may apply, to signal |
| 5296 |
* successful completion. |
| 5297 |
* The callback must be called exactly once, ideally on a later tick of the |
| 5298 |
* JavaScript event loop. |
| 5299 |
* |
| 5300 |
* This type of function is also referred to as a "Node-style async function", |
| 5301 |
* or a "continuation passing-style function" (CPS). Most of the methods of this |
| 5302 |
* library are themselves CPS/Node-style async functions, or functions that |
| 5303 |
* return CPS/Node-style async functions. |
| 5304 |
* |
| 5305 |
* Wherever we accept a Node-style async function, we also directly accept an |
| 5306 |
* [ES2017 `async` function]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function}. |
| 5307 |
* In this case, the `async` function will not be passed a final callback |
| 5308 |
* argument, and any thrown error will be used as the `err` argument of the |
| 5309 |
* implicit callback, and the return value will be used as the `result` value. |
| 5310 |
* (i.e. a `rejected` of the returned Promise becomes the `err` callback |
| 5311 |
* argument, and a `resolved` value becomes the `result`.) |
| 5312 |
* |
| 5313 |
* Note, due to JavaScript limitations, we can only detect native `async` |
| 5314 |
* functions and not transpilied implementations. |
| 5315 |
* Your environment must have `async`/`await` support for this to work. |
| 5316 |
* (e.g. Node > v7.6, or a recent version of a modern browser). |
| 5317 |
* If you are using `async` functions through a transpiler (e.g. Babel), you |
| 5318 |
* must still wrap the function with [asyncify]{@link module:Utils.asyncify}, |
| 5319 |
* because the `async function` will be compiled to an ordinary function that |
| 5320 |
* returns a promise. |
| 5321 |
* |
| 5322 |
* @typedef {Function} AsyncFunction |
| 5323 |
* @static |
| 5324 |
*/ |
| 5325 |
|
| 5326 |
/** |
| 5327 |
* Async is a utility module which provides straight-forward, powerful functions |
| 5328 |
* for working with asynchronous JavaScript. Although originally designed for |
| 5329 |
* use with [Node.js](http://nodejs.org) and installable via |
| 5330 |
* `npm install --save async`, it can also be used directly in the browser. |
| 5331 |
* @module async |
| 5332 |
* @see AsyncFunction |
| 5333 |
*/ |
| 5334 |
|
| 5335 |
|
| 5336 |
/** |
| 5337 |
* A collection of `async` functions for manipulating collections, such as |
| 5338 |
* arrays and objects. |
| 5339 |
* @module Collections |
| 5340 |
*/ |
| 5341 |
|
| 5342 |
/** |
| 5343 |
* A collection of `async` functions for controlling the flow through a script. |
| 5344 |
* @module ControlFlow |
| 5345 |
*/ |
| 5346 |
|
| 5347 |
/** |
| 5348 |
* A collection of `async` utility functions. |
| 5349 |
* @module Utils |
| 5350 |
*/ |
| 5351 |
|
| 5352 |
var index = { |
| 5353 |
applyEach: applyEach, |
| 5354 |
applyEachSeries: applyEachSeries, |
| 5355 |
apply: apply, |
| 5356 |
asyncify: asyncify, |
| 5357 |
auto: auto, |
| 5358 |
autoInject: autoInject, |
| 5359 |
cargo: cargo, |
| 5360 |
compose: compose, |
| 5361 |
concat: concat, |
| 5362 |
concatSeries: concatSeries, |
| 5363 |
constant: constant, |
| 5364 |
detect: detect, |
| 5365 |
detectLimit: detectLimit, |
| 5366 |
detectSeries: detectSeries, |
| 5367 |
dir: dir, |
| 5368 |
doDuring: doDuring, |
| 5369 |
doUntil: doUntil, |
| 5370 |
doWhilst: doWhilst, |
| 5371 |
during: during, |
| 5372 |
each: eachLimit, |
| 5373 |
eachLimit: eachLimit$1, |
| 5374 |
eachOf: eachOf, |
| 5375 |
eachOfLimit: eachOfLimit, |
| 5376 |
eachOfSeries: eachOfSeries, |
| 5377 |
eachSeries: eachSeries, |
| 5378 |
ensureAsync: ensureAsync, |
| 5379 |
every: every, |
| 5380 |
everyLimit: everyLimit, |
| 5381 |
everySeries: everySeries, |
| 5382 |
filter: filter, |
| 5383 |
filterLimit: filterLimit, |
| 5384 |
filterSeries: filterSeries, |
| 5385 |
forever: forever, |
| 5386 |
groupBy: groupBy, |
| 5387 |
groupByLimit: groupByLimit, |
| 5388 |
groupBySeries: groupBySeries, |
| 5389 |
log: log, |
| 5390 |
map: map, |
| 5391 |
mapLimit: mapLimit, |
| 5392 |
mapSeries: mapSeries, |
| 5393 |
mapValues: mapValues, |
| 5394 |
mapValuesLimit: mapValuesLimit, |
| 5395 |
mapValuesSeries: mapValuesSeries, |
| 5396 |
memoize: memoize, |
| 5397 |
nextTick: nextTick, |
| 5398 |
parallel: parallelLimit, |
| 5399 |
parallelLimit: parallelLimit$1, |
| 5400 |
priorityQueue: priorityQueue, |
| 5401 |
queue: queue$1, |
| 5402 |
race: race, |
| 5403 |
reduce: reduce, |
| 5404 |
reduceRight: reduceRight, |
| 5405 |
reflect: reflect, |
| 5406 |
reflectAll: reflectAll, |
| 5407 |
reject: reject, |
| 5408 |
rejectLimit: rejectLimit, |
| 5409 |
rejectSeries: rejectSeries, |
| 5410 |
retry: retry, |
| 5411 |
retryable: retryable, |
| 5412 |
seq: seq, |
| 5413 |
series: series, |
| 5414 |
setImmediate: setImmediate$1, |
| 5415 |
some: some, |
| 5416 |
someLimit: someLimit, |
| 5417 |
someSeries: someSeries, |
| 5418 |
sortBy: sortBy, |
| 5419 |
timeout: timeout, |
| 5420 |
times: times, |
| 5421 |
timesLimit: timeLimit, |
| 5422 |
timesSeries: timesSeries, |
| 5423 |
transform: transform, |
| 5424 |
tryEach: tryEach, |
| 5425 |
unmemoize: unmemoize, |
| 5426 |
until: until, |
| 5427 |
waterfall: waterfall, |
| 5428 |
whilst: whilst, |
| 5429 |
|
| 5430 |
// aliases |
| 5431 |
all: every, |
| 5432 |
any: some, |
| 5433 |
forEach: eachLimit, |
| 5434 |
forEachSeries: eachSeries, |
| 5435 |
forEachLimit: eachLimit$1, |
| 5436 |
forEachOf: eachOf, |
| 5437 |
forEachOfSeries: eachOfSeries, |
| 5438 |
forEachOfLimit: eachOfLimit, |
| 5439 |
inject: reduce, |
| 5440 |
foldl: reduce, |
| 5441 |
foldr: reduceRight, |
| 5442 |
select: filter, |
| 5443 |
selectLimit: filterLimit, |
| 5444 |
selectSeries: filterSeries, |
| 5445 |
wrapSync: asyncify |
| 5446 |
}; |
| 5447 |
|
| 5448 |
exports['default'] = index; |
| 5449 |
exports.applyEach = applyEach; |
| 5450 |
exports.applyEachSeries = applyEachSeries; |
| 5451 |
exports.apply = apply; |
| 5452 |
exports.asyncify = asyncify; |
| 5453 |
exports.auto = auto; |
| 5454 |
exports.autoInject = autoInject; |
| 5455 |
exports.cargo = cargo; |
| 5456 |
exports.compose = compose; |
| 5457 |
exports.concat = concat; |
| 5458 |
exports.concatSeries = concatSeries; |
| 5459 |
exports.constant = constant; |
| 5460 |
exports.detect = detect; |
| 5461 |
exports.detectLimit = detectLimit; |
| 5462 |
exports.detectSeries = detectSeries; |
| 5463 |
exports.dir = dir; |
| 5464 |
exports.doDuring = doDuring; |
| 5465 |
exports.doUntil = doUntil; |
| 5466 |
exports.doWhilst = doWhilst; |
| 5467 |
exports.during = during; |
| 5468 |
exports.each = eachLimit; |
| 5469 |
exports.eachLimit = eachLimit$1; |
| 5470 |
exports.eachOf = eachOf; |
| 5471 |
exports.eachOfLimit = eachOfLimit; |
| 5472 |
exports.eachOfSeries = eachOfSeries; |
| 5473 |
exports.eachSeries = eachSeries; |
| 5474 |
exports.ensureAsync = ensureAsync; |
| 5475 |
exports.every = every; |
| 5476 |
exports.everyLimit = everyLimit; |
| 5477 |
exports.everySeries = everySeries; |
| 5478 |
exports.filter = filter; |
| 5479 |
exports.filterLimit = filterLimit; |
| 5480 |
exports.filterSeries = filterSeries; |
| 5481 |
exports.forever = forever; |
| 5482 |
exports.groupBy = groupBy; |
| 5483 |
exports.groupByLimit = groupByLimit; |
| 5484 |
exports.groupBySeries = groupBySeries; |
| 5485 |
exports.log = log; |
| 5486 |
exports.map = map; |
| 5487 |
exports.mapLimit = mapLimit; |
| 5488 |
exports.mapSeries = mapSeries; |
| 5489 |
exports.mapValues = mapValues; |
| 5490 |
exports.mapValuesLimit = mapValuesLimit; |
| 5491 |
exports.mapValuesSeries = mapValuesSeries; |
| 5492 |
exports.memoize = memoize; |
| 5493 |
exports.nextTick = nextTick; |
| 5494 |
exports.parallel = parallelLimit; |
| 5495 |
exports.parallelLimit = parallelLimit$1; |
| 5496 |
exports.priorityQueue = priorityQueue; |
| 5497 |
exports.queue = queue$1; |
| 5498 |
exports.race = race; |
| 5499 |
exports.reduce = reduce; |
| 5500 |
exports.reduceRight = reduceRight; |
| 5501 |
exports.reflect = reflect; |
| 5502 |
exports.reflectAll = reflectAll; |
| 5503 |
exports.reject = reject; |
| 5504 |
exports.rejectLimit = rejectLimit; |
| 5505 |
exports.rejectSeries = rejectSeries; |
| 5506 |
exports.retry = retry; |
| 5507 |
exports.retryable = retryable; |
| 5508 |
exports.seq = seq; |
| 5509 |
exports.series = series; |
| 5510 |
exports.setImmediate = setImmediate$1; |
| 5511 |
exports.some = some; |
| 5512 |
exports.someLimit = someLimit; |
| 5513 |
exports.someSeries = someSeries; |
| 5514 |
exports.sortBy = sortBy; |
| 5515 |
exports.timeout = timeout; |
| 5516 |
exports.times = times; |
| 5517 |
exports.timesLimit = timeLimit; |
| 5518 |
exports.timesSeries = timesSeries; |
| 5519 |
exports.transform = transform; |
| 5520 |
exports.tryEach = tryEach; |
| 5521 |
exports.unmemoize = unmemoize; |
| 5522 |
exports.until = until; |
| 5523 |
exports.waterfall = waterfall; |
| 5524 |
exports.whilst = whilst; |
| 5525 |
exports.all = every; |
| 5526 |
exports.allLimit = everyLimit; |
| 5527 |
exports.allSeries = everySeries; |
| 5528 |
exports.any = some; |
| 5529 |
exports.anyLimit = someLimit; |
| 5530 |
exports.anySeries = someSeries; |
| 5531 |
exports.find = detect; |
| 5532 |
exports.findLimit = detectLimit; |
| 5533 |
exports.findSeries = detectSeries; |
| 5534 |
exports.forEach = eachLimit; |
| 5535 |
exports.forEachSeries = eachSeries; |
| 5536 |
exports.forEachLimit = eachLimit$1; |
| 5537 |
exports.forEachOf = eachOf; |
| 5538 |
exports.forEachOfSeries = eachOfSeries; |
| 5539 |
exports.forEachOfLimit = eachOfLimit; |
| 5540 |
exports.inject = reduce; |
| 5541 |
exports.foldl = reduce; |
| 5542 |
exports.foldr = reduceRight; |
| 5543 |
exports.select = filter; |
| 5544 |
exports.selectLimit = filterLimit; |
| 5545 |
exports.selectSeries = filterSeries; |
| 5546 |
exports.wrapSync = asyncify; |
| 5547 |
|
| 5548 |
Object.defineProperty(exports, '__esModule', { value: true }); |
| 5549 |
|
| 5550 |
}))); |
| 5551 |
|