index.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. 'use strict'
  2. module.exports = function (PromiseArgument) {
  3. var Promise;
  4. function throat(size, fn) {
  5. var queue = []
  6. function run(fn, self, args) {
  7. if (size) {
  8. size--
  9. var result = new Promise(function (resolve) {
  10. resolve(fn.apply(self, args))
  11. })
  12. result.then(release, release)
  13. return result
  14. } else {
  15. return new Promise(function (resolve) {
  16. queue.push(new Delayed(resolve, fn, self, args))
  17. })
  18. }
  19. }
  20. function release() {
  21. size++
  22. if (queue.length) {
  23. var next = queue.shift()
  24. next.resolve(run(next.fn, next.self, next.args))
  25. }
  26. }
  27. if (typeof size === 'function') {
  28. var temp = fn;
  29. fn = size;
  30. size = temp;
  31. }
  32. if (typeof size !== 'number') {
  33. throw new TypeError(
  34. 'Expected throat size to be a number but got ' + typeof size
  35. );
  36. }
  37. if (fn !== undefined && typeof fn !== 'function') {
  38. throw new TypeError(
  39. 'Expected throat fn to be a function but got ' + typeof fn
  40. );
  41. }
  42. if (typeof fn === 'function') {
  43. return function () {
  44. var args = [];
  45. for (var i = 0; i < arguments.length; i++) {
  46. args.push(arguments[i]);
  47. }
  48. return run(fn, this, args);
  49. }
  50. } else {
  51. return function (fn) {
  52. if (typeof fn !== 'function') {
  53. throw new TypeError(
  54. 'Expected throat fn to be a function but got ' + typeof fn
  55. );
  56. }
  57. var args = [];
  58. for (var i = 1; i < arguments.length; i++) {
  59. args.push(arguments[i]);
  60. }
  61. return run(fn, this, args);
  62. }
  63. }
  64. }
  65. if (arguments.length === 1 && typeof PromiseArgument === 'function') {
  66. Promise = PromiseArgument;
  67. return throat;
  68. } else {
  69. Promise = module.exports.Promise;
  70. if (typeof Promise !== 'function') {
  71. throw new Error(
  72. 'You must provide a Promise polyfill for this library to work in older environments'
  73. );
  74. }
  75. return throat(arguments[0], arguments[1]);
  76. }
  77. }
  78. /* istanbul ignore next */
  79. if (typeof Promise === 'function') {
  80. module.exports.Promise = Promise;
  81. }
  82. function Delayed(resolve, fn, self, args) {
  83. this.resolve = resolve
  84. this.fn = fn
  85. this.self = self || null
  86. this.args = args
  87. }