62 lines
1.5 KiB
JavaScript
62 lines
1.5 KiB
JavaScript
"use strict";
|
|
|
|
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); }
|
|
});
|
|
};
|