You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
63 lines
1.5 KiB
63 lines
1.5 KiB
2 years ago
|
"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); }
|
||
|
});
|
||
|
};
|