Spaces:
Runtime error
Runtime error
; | |
var ensureNaturalNumber = require("type/natural-number/ensure") | |
, ensurePlainFunction = require("type/plain-function/ensure") | |
, ensure = require("type/ensure") | |
, defineFunctionLength = require("../lib/private/define-function-length"); | |
module.exports = function (limit, callback) { | |
limit = ensure( | |
["limit", limit, ensureNaturalNumber, { min: 1 }], | |
["callback", callback, ensurePlainFunction] | |
)[0]; | |
var Promise = this, ongoingCount = 0, pending = []; | |
var onSuccess, onFailure; | |
var release = function () { | |
--ongoingCount; | |
if (ongoingCount >= limit) return; | |
var next = pending.shift(); | |
if (!next) return; | |
++ongoingCount; | |
try { | |
next.resolve( | |
Promise.resolve(callback.apply(next.context, next.arguments)).then( | |
onSuccess, onFailure | |
) | |
); | |
} catch (exception) { | |
release(); | |
next.reject(exception); | |
} | |
}; | |
onSuccess = function (value) { | |
release(); | |
return value; | |
}; | |
onFailure = function (exception) { | |
release(); | |
throw exception; | |
}; | |
return defineFunctionLength(callback.length, function () { | |
if (ongoingCount >= limit) { | |
var context = this, args = arguments; | |
return new Promise(function (resolve, reject) { | |
pending.push({ | |
context: context, | |
arguments: args, | |
resolve: resolve, | |
reject: reject | |
}); | |
}); | |
} | |
++ongoingCount; | |
try { | |
return Promise.resolve(callback.apply(this, arguments)).then(onSuccess, onFailure); | |
} catch (exception) { return onFailure(exception); } | |
}); | |
}; | |