@chriscdn/promise-semaphore 2.0.11 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,12 +16,26 @@ Using yarn:
16
16
  yarn add @chriscdn/promise-semaphore
17
17
  ```
18
18
 
19
+ ## Upgrade to v3
20
+
21
+ Change
22
+
23
+ ```ts
24
+ import Semaphore from "@chriscdn/promise-semaphore";
25
+ ```
26
+
27
+ to
28
+
29
+ ```ts
30
+ import { Semaphore } from "@chriscdn/promise-semaphore";
31
+ ```
32
+
19
33
  ## API
20
34
 
21
35
  ### Create an instance
22
36
 
23
37
  ```js
24
- import Semaphore from "@chriscdn/promise-semaphore";
38
+ import { Semaphore } from "@chriscdn/promise-semaphore";
25
39
  const semaphore = new Semaphore([maxConcurrent]);
26
40
  ```
27
41
 
@@ -59,14 +73,6 @@ semaphore.count([key]);
59
73
 
60
74
  This synchronous function returns the current number of locks.
61
75
 
62
- ### `wait` method
63
-
64
- ```js
65
- semaphore.wait([key]);
66
- ```
67
-
68
- This asynchronous function resolves immediately if `count` is 0; otherwise, it resolves once `count` reaches 0.
69
-
70
76
  ### `request` method
71
77
 
72
78
  ```js
@@ -103,7 +109,7 @@ This is useful in scenarios where only one instance of a function block should r
103
109
  ## Example 1
104
110
 
105
111
  ```js
106
- import Semaphore from "@chriscdn/promise-semaphore";
112
+ import { Semaphore } from "@chriscdn/promise-semaphore";
107
113
  const semaphore = new Semaphore();
108
114
 
109
115
  // Using promises
@@ -158,7 +164,7 @@ This approach works as expected until `downloadAndSave()` is called multiple tim
158
164
  This issue can be resolved by using a `Semaphore` with the `key` parameter:
159
165
 
160
166
  ```js
161
- import Semaphore from "@chriscdn/promise-semaphore";
167
+ import { Semaphore } from "@chriscdn/promise-semaphore";
162
168
  const semaphore = new Semaphore();
163
169
 
164
170
  const downloadAndSave = async (url) => {
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
 
3
- import Semaphore from "../src/index";
3
+ import { Semaphore } from "../src/index";
4
4
 
5
5
  const pause = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
6
6
 
@@ -145,26 +145,3 @@ describe("All test", () => {
145
145
  });
146
146
  });
147
147
  });
148
-
149
- describe("Wait TEST", () => {
150
- const semaphore = new Semaphore(2);
151
-
152
- it("Acquire & Release Basic", async () => {
153
- let tester = 0;
154
-
155
- semaphore
156
- .acquire()
157
- .then(() => pause(1000))
158
- .then(() => (tester = 20))
159
- .finally(() => semaphore.release());
160
-
161
- semaphore
162
- .acquire()
163
- .then(() => pause(500))
164
- .then(() => (tester = 10))
165
- .finally(() => semaphore.release());
166
-
167
- await semaphore.wait(); // WAIT for all tasks to finish
168
- expect(tester).toBe(20);
169
- });
170
- });
package/lib/index.d.ts CHANGED
@@ -53,6 +53,5 @@ declare class Semaphore {
53
53
  * @returns {Promise<T>}
54
54
  */
55
55
  requestIfAvailable<T>(fn: Function, key?: string | number): Promise<T | null>;
56
- wait(key?: string | number): Promise<void>;
57
56
  }
58
- export default Semaphore;
57
+ export { Semaphore };
@@ -1,2 +1,2 @@
1
- function e(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}var t=/*#__PURE__*/function(){function t(e){this.queue=void 0,this.waitQueue=void 0,this.maxConcurrent=void 0,this.count=void 0,this.queue=[],this.waitQueue=[],this.maxConcurrent=e,this.count=0}var n,r,i=t.prototype;return i.incrementCount=function(){this.count++},i.decrementCount=function(){this.count--,0===this.count&&(this.waitQueue.forEach(function(e){return e()}),this.waitQueue=[])},i.acquire=function(){var e=this;return this.canAcquire?(this.incrementCount(),Promise.resolve()):new Promise(function(t){return e.queue.push(t)})},i.release=function(){var e=this.queue.shift();e?setTimeout(e,0):this.decrementCount()},i.wait=function(){var e=this;return new Promise(function(t){return e.waitQueue.push(t)})},n=t,(r=[{key:"canAcquire",get:function(){return this.count<this.maxConcurrent}}])&&function(t,n){for(var r=0;r<n.length;r++){var i=n[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,e(i.key),i)}}(n.prototype,r),Object.defineProperty(n,"prototype",{writable:!1}),n}(),n="_default";module.exports=/*#__PURE__*/function(){function e(e){void 0===e&&(e=1),this.semaphoreInstances=void 0,this.maxConcurrent=void 0,this.semaphoreInstances={},this.maxConcurrent=e}var r=e.prototype;return r.hasSemaphoreInstance=function(e){return void 0===e&&(e=n),Boolean(this.semaphoreInstances[e])},r.getSemaphoreInstance=function(e){return void 0===e&&(e=n),this.hasSemaphoreInstance(e)||(this.semaphoreInstances[e]=new t(this.maxConcurrent)),this.semaphoreInstances[e]},r.tidy=function(e){void 0===e&&(e=n),this.hasSemaphoreInstance(e)&&0===this.getSemaphoreInstance(e).count&&delete this.semaphoreInstances[e]},r.canAcquire=function(e){return void 0===e&&(e=n),this.getSemaphoreInstance(e).canAcquire},r.acquire=function(e){return void 0===e&&(e=n),this.getSemaphoreInstance(e).acquire()},r.release=function(e){void 0===e&&(e=n),this.getSemaphoreInstance(e).release(),this.tidy(e)},r.count=function(e){return void 0===e&&(e=n),this.hasSemaphoreInstance(e)?this.getSemaphoreInstance(e).count:0},r.hasTasks=function(e){return void 0===e&&(e=n),this.count(e)>0},r.request=function(e,t){void 0===t&&(t=n);try{var r=this;return Promise.resolve(function(n,i){try{var o=Promise.resolve(r.acquire(t)).then(function(){return Promise.resolve(e())})}catch(e){return i(!0,e)}return o&&o.then?o.then(i.bind(null,!1),i.bind(null,!0)):i(!1,o)}(0,function(e,n){if(r.release(t),e)throw n;return n}))}catch(e){return Promise.reject(e)}},r.requestIfAvailable=function(e,t){void 0===t&&(t=n);try{return this.canAcquire(t)?Promise.resolve(this.request(e,t)):Promise.resolve(null)}catch(e){return Promise.reject(e)}},r.wait=function(e){void 0===e&&(e=n);try{return this.hasTasks(e)?Promise.resolve(this.getSemaphoreInstance(e).wait()):Promise.resolve()}catch(e){return Promise.reject(e)}},e}();
1
+ function e(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}var t=/*#__PURE__*/function(){function t(e){this.queue=void 0,this.maxConcurrent=void 0,this.count=void 0,this.queue=[],this.maxConcurrent=e,this.count=0}var n,r,i=t.prototype;return i.incrementCount=function(){this.count++},i.decrementCount=function(){this.count--},i.acquire=function(){var e=this;return this.canAcquire?(this.incrementCount(),Promise.resolve()):new Promise(function(t){return e.queue.push(t)})},i.release=function(){var e=this.queue.shift();e?setTimeout(e,0):this.decrementCount()},n=t,(r=[{key:"canAcquire",get:function(){return this.count<this.maxConcurrent}}])&&function(t,n){for(var r=0;r<n.length;r++){var i=n[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,e(i.key),i)}}(n.prototype,r),Object.defineProperty(n,"prototype",{writable:!1}),n}(),n="_default";exports.Semaphore=/*#__PURE__*/function(){function e(e){void 0===e&&(e=1),this.semaphoreInstances=void 0,this.maxConcurrent=void 0,this.semaphoreInstances={},this.maxConcurrent=e}var r=e.prototype;return r.hasSemaphoreInstance=function(e){return void 0===e&&(e=n),Boolean(this.semaphoreInstances[e])},r.getSemaphoreInstance=function(e){return void 0===e&&(e=n),this.hasSemaphoreInstance(e)||(this.semaphoreInstances[e]=new t(this.maxConcurrent)),this.semaphoreInstances[e]},r.tidy=function(e){void 0===e&&(e=n),this.hasSemaphoreInstance(e)&&0===this.getSemaphoreInstance(e).count&&delete this.semaphoreInstances[e]},r.canAcquire=function(e){return void 0===e&&(e=n),!this.hasSemaphoreInstance(e)||this.getSemaphoreInstance(e).canAcquire},r.acquire=function(e){return void 0===e&&(e=n),this.getSemaphoreInstance(e).acquire()},r.release=function(e){void 0===e&&(e=n),this.getSemaphoreInstance(e).release(),this.tidy(e)},r.count=function(e){return void 0===e&&(e=n),this.hasSemaphoreInstance(e)?this.getSemaphoreInstance(e).count:0},r.hasTasks=function(e){return void 0===e&&(e=n),this.count(e)>0},r.request=function(e,t){void 0===t&&(t=n);try{var r=this;return Promise.resolve(function(n,i){try{var o=Promise.resolve(r.acquire(t)).then(function(){return Promise.resolve(e())})}catch(e){return i(!0,e)}return o&&o.then?o.then(i.bind(null,!1),i.bind(null,!0)):i(!1,o)}(0,function(e,n){if(r.release(t),e)throw n;return n}))}catch(e){return Promise.reject(e)}},r.requestIfAvailable=function(e,t){void 0===t&&(t=n);try{return this.canAcquire(t)?Promise.resolve(this.request(e,t)):Promise.resolve(null)}catch(e){return Promise.reject(e)}},e}();
2
2
  //# sourceMappingURL=promise-semaphore.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"promise-semaphore.cjs","sources":["../src/index.ts"],"sourcesContent":["class SemaphoreItem {\n private queue: Array<Function>;\n private waitQueue: Array<Function>;\n private maxConcurrent: number;\n\n /**\n * The number of locks.\n */\n public count: number;\n\n constructor(maxConcurrent: number) {\n this.queue = [];\n this.waitQueue = [];\n this.maxConcurrent = maxConcurrent;\n this.count = 0;\n }\n\n get canAcquire(): boolean {\n return this.count < this.maxConcurrent;\n }\n\n private incrementCount() {\n this.count++;\n }\n\n private decrementCount() {\n this.count--;\n\n if (this.count === 0) {\n this.waitQueue.forEach((resolve) => resolve());\n this.waitQueue = [];\n }\n }\n\n acquire(): Promise<void> {\n if (this.canAcquire) {\n this.incrementCount();\n return Promise.resolve();\n } else {\n return new Promise((resolve) => this.queue.push(resolve));\n }\n }\n\n release(): void {\n const resolveFunc = this.queue.shift();\n\n if (resolveFunc) {\n // Give the micro task queue a small break instead of calling resolveFunc() directly\n setTimeout(resolveFunc, 0);\n } else {\n this.decrementCount();\n }\n }\n\n wait(): Promise<void> {\n return new Promise((resolve) => this.waitQueue.push(resolve));\n }\n}\n\nconst defaultKey = \"_default\";\n\nclass Semaphore {\n private semaphoreInstances: Record<string | number, SemaphoreItem>;\n private maxConcurrent: number;\n\n /**\n * @param {number} [maxConcurrent] The maximum number of concurrent locks.\n */\n constructor(maxConcurrent: number = 1) {\n this.semaphoreInstances = {};\n this.maxConcurrent = maxConcurrent;\n }\n\n private hasSemaphoreInstance(key: string | number = defaultKey) {\n return Boolean(this.semaphoreInstances[key]);\n }\n\n private getSemaphoreInstance(key: string | number = defaultKey) {\n if (!this.hasSemaphoreInstance(key)) {\n this.semaphoreInstances[key] = new SemaphoreItem(this.maxConcurrent);\n }\n return this.semaphoreInstances[key];\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n private tidy(key: string | number = defaultKey): void {\n if (\n this.hasSemaphoreInstance(key) &&\n this.getSemaphoreInstance(key).count === 0\n ) {\n delete this.semaphoreInstances[key];\n }\n }\n\n /**\n * A synchronous function to determine whether a lock can be acquired.\n *\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {boolean} Returns true if the lock on `key` can be acquired, false\n * otherwise.\n */\n canAcquire(key: string | number = defaultKey): boolean {\n return this.getSemaphoreInstance(key).canAcquire;\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n acquire(key: string | number = defaultKey) {\n return this.getSemaphoreInstance(key).acquire();\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n release(key: string | number = defaultKey): void {\n this.getSemaphoreInstance(key).release();\n this.tidy(key);\n }\n\n /**\n * The number of active locks. Will always be less or equal to `max`.\n *\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n count(key: string | number = defaultKey): number {\n if (this.hasSemaphoreInstance(key)) {\n return this.getSemaphoreInstance(key).count;\n } else {\n return 0;\n }\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {boolean} True if the semaphore and key has locks, false otherwise.\n */\n hasTasks(key: string | number = defaultKey): boolean {\n return this.count(key) > 0;\n }\n\n /**\n * @param {Function<T>} fn The function to execute.\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {Promise<T>}\n */\n async request<T>(\n fn: Function,\n key: string | number = defaultKey,\n ): Promise<T> {\n try {\n await this.acquire(key);\n return await fn();\n } finally {\n this.release(key);\n }\n }\n\n /**\n * Asynchronously executes `fn` if a lock can be immediately acquired.\n * Otherwise, returns null.\n *\n * @param {Function<T>} fn The function to execute.\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {Promise<T>}\n */\n async requestIfAvailable<T>(\n fn: Function,\n key: string | number = defaultKey,\n ): Promise<T | null> {\n if (this.canAcquire(key)) {\n return this.request(fn, key);\n } else {\n return null;\n }\n }\n\n async wait(key: string | number = defaultKey) {\n if (this.hasTasks(key)) {\n return this.getSemaphoreInstance(key).wait();\n } else {\n return Promise.resolve();\n }\n }\n}\n\nexport default Semaphore;\n"],"names":["SemaphoreItem","maxConcurrent","queue","waitQueue","count","this","_proto","prototype","incrementCount","decrementCount","forEach","resolve","acquire","_this","canAcquire","Promise","push","release","resolveFunc","shift","setTimeout","wait","_this2","key","get","defaultKey","Semaphore","semaphoreInstances","_proto2","hasSemaphoreInstance","Boolean","getSemaphoreInstance","tidy","hasTasks","request","fn","_this3","then","_finallyRethrows","_wasThrown","_result","e","reject","requestIfAvailable"],"mappings":"mSAAMA,eAUJ,WAAA,SAAAA,EAAYC,GATJC,KAAAA,WACAC,EAAAA,KAAAA,eACAF,EAAAA,KAAAA,0BAKDG,WAAK,EAGVC,KAAKH,MAAQ,GACbG,KAAKF,UAAY,GACjBE,KAAKJ,cAAgBA,EACrBI,KAAKD,MAAQ,CACf,CAAC,QAAAE,EAAAN,EAAAO,iBAAAD,EAMOE,eAAA,WACNH,KAAKD,OACP,EAACE,EAEOG,eAAA,WACNJ,KAAKD,QAEc,IAAfC,KAAKD,QACPC,KAAKF,UAAUO,QAAQ,SAACC,UAAYA,GAAS,GAC7CN,KAAKF,UAAY,GAErB,EAACG,EAEDM,QAAA,WAAO,IAAAC,EACLR,KAAA,OAAIA,KAAKS,YACPT,KAAKG,iBACEO,QAAQJ,WAER,IAAII,QAAQ,SAACJ,UAAYE,EAAKX,MAAMc,KAAKL,EAAQ,EAE5D,EAACL,EAEDW,QAAA,WACE,IAAMC,EAAcb,KAAKH,MAAMiB,QAE3BD,EAEFE,WAAWF,EAAa,GAExBb,KAAKI,gBAET,EAACH,EAEDe,KAAA,WAAI,IAAAC,EACFjB,KAAA,OAAW,IAAAU,QAAQ,SAACJ,GAAO,OAAKW,EAAKnB,UAAUa,KAAKL,EAAQ,EAC9D,IAACX,KAAA,CAAA,CAAAuB,IAAA,aAAAC,IAvCD,WACE,YAAYpB,MAAQC,KAAKJ,aAC3B,iPAwCF,CAjDE,GAiDIwB,EAAa,uCASjB,WAAA,SAAAC,EAAYzB,QAAAA,IAAAA,IAAAA,EAAwB,GAACI,KAN7BsB,wBAAkB,EAAAtB,KAClBJ,mBAAa,EAMnBI,KAAKsB,mBAAqB,CAAE,EAC5BtB,KAAKJ,cAAgBA,CACvB,CAAC,IAAA2B,EAAAF,EAAAnB,iBAAAqB,EAEOC,qBAAA,SAAqBN,GAC3B,gBAD2BA,IAAAA,EAAuBE,GAC3CK,QAAQzB,KAAKsB,mBAAmBJ,GACzC,EAACK,EAEOG,qBAAA,SAAqBR,GAI3B,YAJ2BA,IAAAA,IAAAA,EAAuBE,GAC7CpB,KAAKwB,qBAAqBN,KAC7BlB,KAAKsB,mBAAmBJ,GAAO,IAAIvB,EAAcK,KAAKJ,gBAE7CI,KAACsB,mBAAmBJ,EACjC,EAACK,EAKOI,KAAA,SAAKT,QAAAA,IAAAA,IAAAA,EAAuBE,GAEhCpB,KAAKwB,qBAAqBN,IACe,IAAzClB,KAAK0B,qBAAqBR,GAAKnB,cAExBC,KAAKsB,mBAAmBJ,EAEnC,EAACK,EASDd,WAAA,SAAWS,GACT,gBADSA,IAAAA,EAAuBE,GACrBpB,KAAC0B,qBAAqBR,GAAKT,UACxC,EAACc,EAKDhB,QAAA,SAAQW,GACN,YADMA,IAAAA,IAAAA,EAAuBE,GACtBpB,KAAK0B,qBAAqBR,GAAKX,SACxC,EAACgB,EAKDX,QAAA,SAAQM,YAAAA,IAAAA,EAAuBE,GAC7BpB,KAAK0B,qBAAqBR,GAAKN,UAC/BZ,KAAK2B,KAAKT,EACZ,EAACK,EAODxB,MAAA,SAAMmB,GACJ,gBADIA,IAAAA,EAAuBE,GACvBpB,KAAKwB,qBAAqBN,GACrBlB,KAAK0B,qBAAqBR,GAAKnB,OAI1C,EAACwB,EAMDK,SAAA,SAASV,GACP,YADOA,IAAAA,IAAAA,EAAuBE,QAClBrB,MAAMmB,GAAO,CAC3B,EAACK,EAOKM,iBACJC,EACAZ,YAAAA,IAAAA,EAAuBE,GAAU,QAAAW,EAGzB/B,KAAI,OAAAU,QAAAJ,gCADRI,QAAAJ,QACIyB,EAAKxB,QAAQW,IAAIc,KAAAtB,WAAAA,OAAAA,QAAAJ,QACVwB,IAAI,4FADPG,CADR,EAGH,SAAAC,EAAAC,GACmB,GAAlBJ,EAAKnB,QAAQM,GAAKgB,QAAAC,EAAA,OAAAA,CAAA,GAEtB,CAAC,MAAAC,GAAA1B,OAAAA,QAAA2B,OAAAD,KAAAb,EAUKe,mBAAkB,SACtBR,EACAZ,YAAAA,IAAAA,EAAuBE,GAAU,IAEjC,OAAIpB,KAAKS,WAAWS,GAClBR,QAAAJ,QADEN,KACU6B,QAAQC,EAAIZ,IAExBR,QAAAJ,QAAO,KAEX,CAAC,MAAA8B,GAAA1B,OAAAA,QAAA2B,OAAAD,EAAA,CAAA,EAAAb,EAEKP,KAAA,SAAKE,QAAAA,IAAAA,IAAAA,EAAuBE,GAAU,IAC1C,OAAIpB,KAAK4B,SAASV,GAChBR,QAAAJ,QADEN,KACU0B,qBAAqBR,GAAKF,QAE/BN,QAAQJ,SAEnB,CAAC,MAAA8B,GAAA1B,OAAAA,QAAA2B,OAAAD,KAAAf,CAAA,CArHD"}
1
+ {"version":3,"file":"promise-semaphore.cjs","sources":["../src/index.ts"],"sourcesContent":["class SemaphoreItem {\n private queue: Function[];\n private maxConcurrent: number;\n\n /**\n * The number of locks.\n */\n public count: number;\n\n constructor(maxConcurrent: number) {\n this.queue = [];\n this.maxConcurrent = maxConcurrent;\n this.count = 0;\n }\n\n get canAcquire(): boolean {\n return this.count < this.maxConcurrent;\n }\n\n private incrementCount() {\n this.count++;\n }\n\n private decrementCount() {\n this.count--;\n }\n\n acquire(): Promise<void> {\n if (this.canAcquire) {\n this.incrementCount();\n return Promise.resolve();\n } else {\n return new Promise((resolve) => this.queue.push(resolve));\n }\n }\n\n release(): void {\n const resolveFunc = this.queue.shift();\n\n if (resolveFunc) {\n // Give the micro task queue a small break instead of calling resolveFunc() directly\n setTimeout(resolveFunc, 0);\n } else {\n this.decrementCount();\n }\n }\n}\n\nconst defaultKey = \"_default\";\n\nclass Semaphore {\n private semaphoreInstances: Record<string | number, SemaphoreItem>;\n private maxConcurrent: number;\n\n /**\n * @param {number} [maxConcurrent] The maximum number of concurrent locks.\n */\n constructor(maxConcurrent: number = 1) {\n this.semaphoreInstances = {};\n this.maxConcurrent = maxConcurrent;\n }\n\n private hasSemaphoreInstance(key: string | number = defaultKey) {\n return Boolean(this.semaphoreInstances[key]);\n }\n\n private getSemaphoreInstance(key: string | number = defaultKey) {\n if (!this.hasSemaphoreInstance(key)) {\n this.semaphoreInstances[key] = new SemaphoreItem(this.maxConcurrent);\n }\n return this.semaphoreInstances[key];\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n private tidy(key: string | number = defaultKey): void {\n if (\n this.hasSemaphoreInstance(key) &&\n this.getSemaphoreInstance(key).count === 0\n ) {\n delete this.semaphoreInstances[key];\n }\n }\n\n /**\n * A synchronous function to determine whether a lock can be acquired.\n *\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {boolean} Returns true if the lock on `key` can be acquired, false\n * otherwise.\n */\n canAcquire(key: string | number = defaultKey): boolean {\n return !this.hasSemaphoreInstance(key) ||\n this.getSemaphoreInstance(key).canAcquire;\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n acquire(key: string | number = defaultKey) {\n return this.getSemaphoreInstance(key).acquire();\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n release(key: string | number = defaultKey): void {\n this.getSemaphoreInstance(key).release();\n this.tidy(key);\n }\n\n /**\n * The number of active locks. Will always be less or equal to `max`.\n *\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n count(key: string | number = defaultKey): number {\n if (this.hasSemaphoreInstance(key)) {\n return this.getSemaphoreInstance(key).count;\n } else {\n return 0;\n }\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {boolean} True if the semaphore and key has locks, false otherwise.\n */\n hasTasks(key: string | number = defaultKey): boolean {\n return this.count(key) > 0;\n }\n\n /**\n * @param {Function<T>} fn The function to execute.\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {Promise<T>}\n */\n async request<T>(\n fn: Function,\n key: string | number = defaultKey,\n ): Promise<T> {\n try {\n await this.acquire(key);\n return await fn();\n } finally {\n this.release(key);\n }\n }\n\n /**\n * Asynchronously executes `fn` if a lock can be immediately acquired.\n * Otherwise, returns null.\n *\n * @param {Function<T>} fn The function to execute.\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {Promise<T>}\n */\n async requestIfAvailable<T>(\n fn: Function,\n key: string | number = defaultKey,\n ): Promise<T | null> {\n if (this.canAcquire(key)) {\n return this.request(fn, key);\n } else {\n return null;\n }\n }\n}\n\nexport { Semaphore };\n"],"names":["SemaphoreItem","maxConcurrent","queue","this","count","_proto","prototype","incrementCount","decrementCount","acquire","_this","canAcquire","Promise","resolve","push","release","resolveFunc","shift","setTimeout","key","get","defaultKey","Semaphore","semaphoreInstances","_proto2","hasSemaphoreInstance","Boolean","getSemaphoreInstance","tidy","hasTasks","request","fn","_this2","then","_finallyRethrows","_wasThrown","_result","e","reject","requestIfAvailable"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- class e{constructor(e){this.queue=void 0,this.waitQueue=void 0,this.maxConcurrent=void 0,this.count=void 0,this.queue=[],this.waitQueue=[],this.maxConcurrent=e,this.count=0}get canAcquire(){return this.count<this.maxConcurrent}incrementCount(){this.count++}decrementCount(){this.count--,0===this.count&&(this.waitQueue.forEach(e=>e()),this.waitQueue=[])}acquire(){return this.canAcquire?(this.incrementCount(),Promise.resolve()):new Promise(e=>this.queue.push(e))}release(){const e=this.queue.shift();e?setTimeout(e,0):this.decrementCount()}wait(){return new Promise(e=>this.waitQueue.push(e))}}const t="_default";class s{constructor(e=1){this.semaphoreInstances=void 0,this.maxConcurrent=void 0,this.semaphoreInstances={},this.maxConcurrent=e}hasSemaphoreInstance(e=t){return Boolean(this.semaphoreInstances[e])}getSemaphoreInstance(s=t){return this.hasSemaphoreInstance(s)||(this.semaphoreInstances[s]=new e(this.maxConcurrent)),this.semaphoreInstances[s]}tidy(e=t){this.hasSemaphoreInstance(e)&&0===this.getSemaphoreInstance(e).count&&delete this.semaphoreInstances[e]}canAcquire(e=t){return this.getSemaphoreInstance(e).canAcquire}acquire(e=t){return this.getSemaphoreInstance(e).acquire()}release(e=t){this.getSemaphoreInstance(e).release(),this.tidy(e)}count(e=t){return this.hasSemaphoreInstance(e)?this.getSemaphoreInstance(e).count:0}hasTasks(e=t){return this.count(e)>0}async request(e,s=t){try{return await this.acquire(s),await e()}finally{this.release(s)}}async requestIfAvailable(e,s=t){return this.canAcquire(s)?this.request(e,s):null}async wait(e=t){return this.hasTasks(e)?this.getSemaphoreInstance(e).wait():Promise.resolve()}}export{s as default};
1
+ class e{constructor(e){this.queue=void 0,this.maxConcurrent=void 0,this.count=void 0,this.queue=[],this.maxConcurrent=e,this.count=0}get canAcquire(){return this.count<this.maxConcurrent}incrementCount(){this.count++}decrementCount(){this.count--}acquire(){return this.canAcquire?(this.incrementCount(),Promise.resolve()):new Promise(e=>this.queue.push(e))}release(){const e=this.queue.shift();e?setTimeout(e,0):this.decrementCount()}}const t="_default";class s{constructor(e=1){this.semaphoreInstances=void 0,this.maxConcurrent=void 0,this.semaphoreInstances={},this.maxConcurrent=e}hasSemaphoreInstance(e=t){return Boolean(this.semaphoreInstances[e])}getSemaphoreInstance(s=t){return this.hasSemaphoreInstance(s)||(this.semaphoreInstances[s]=new e(this.maxConcurrent)),this.semaphoreInstances[s]}tidy(e=t){this.hasSemaphoreInstance(e)&&0===this.getSemaphoreInstance(e).count&&delete this.semaphoreInstances[e]}canAcquire(e=t){return!this.hasSemaphoreInstance(e)||this.getSemaphoreInstance(e).canAcquire}acquire(e=t){return this.getSemaphoreInstance(e).acquire()}release(e=t){this.getSemaphoreInstance(e).release(),this.tidy(e)}count(e=t){return this.hasSemaphoreInstance(e)?this.getSemaphoreInstance(e).count:0}hasTasks(e=t){return this.count(e)>0}async request(e,s=t){try{return await this.acquire(s),await e()}finally{this.release(s)}}async requestIfAvailable(e,s=t){return this.canAcquire(s)?this.request(e,s):null}}export{s as Semaphore};
2
2
  //# sourceMappingURL=promise-semaphore.modern.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"promise-semaphore.modern.js","sources":["../src/index.ts"],"sourcesContent":["class SemaphoreItem {\n private queue: Array<Function>;\n private waitQueue: Array<Function>;\n private maxConcurrent: number;\n\n /**\n * The number of locks.\n */\n public count: number;\n\n constructor(maxConcurrent: number) {\n this.queue = [];\n this.waitQueue = [];\n this.maxConcurrent = maxConcurrent;\n this.count = 0;\n }\n\n get canAcquire(): boolean {\n return this.count < this.maxConcurrent;\n }\n\n private incrementCount() {\n this.count++;\n }\n\n private decrementCount() {\n this.count--;\n\n if (this.count === 0) {\n this.waitQueue.forEach((resolve) => resolve());\n this.waitQueue = [];\n }\n }\n\n acquire(): Promise<void> {\n if (this.canAcquire) {\n this.incrementCount();\n return Promise.resolve();\n } else {\n return new Promise((resolve) => this.queue.push(resolve));\n }\n }\n\n release(): void {\n const resolveFunc = this.queue.shift();\n\n if (resolveFunc) {\n // Give the micro task queue a small break instead of calling resolveFunc() directly\n setTimeout(resolveFunc, 0);\n } else {\n this.decrementCount();\n }\n }\n\n wait(): Promise<void> {\n return new Promise((resolve) => this.waitQueue.push(resolve));\n }\n}\n\nconst defaultKey = \"_default\";\n\nclass Semaphore {\n private semaphoreInstances: Record<string | number, SemaphoreItem>;\n private maxConcurrent: number;\n\n /**\n * @param {number} [maxConcurrent] The maximum number of concurrent locks.\n */\n constructor(maxConcurrent: number = 1) {\n this.semaphoreInstances = {};\n this.maxConcurrent = maxConcurrent;\n }\n\n private hasSemaphoreInstance(key: string | number = defaultKey) {\n return Boolean(this.semaphoreInstances[key]);\n }\n\n private getSemaphoreInstance(key: string | number = defaultKey) {\n if (!this.hasSemaphoreInstance(key)) {\n this.semaphoreInstances[key] = new SemaphoreItem(this.maxConcurrent);\n }\n return this.semaphoreInstances[key];\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n private tidy(key: string | number = defaultKey): void {\n if (\n this.hasSemaphoreInstance(key) &&\n this.getSemaphoreInstance(key).count === 0\n ) {\n delete this.semaphoreInstances[key];\n }\n }\n\n /**\n * A synchronous function to determine whether a lock can be acquired.\n *\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {boolean} Returns true if the lock on `key` can be acquired, false\n * otherwise.\n */\n canAcquire(key: string | number = defaultKey): boolean {\n return this.getSemaphoreInstance(key).canAcquire;\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n acquire(key: string | number = defaultKey) {\n return this.getSemaphoreInstance(key).acquire();\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n release(key: string | number = defaultKey): void {\n this.getSemaphoreInstance(key).release();\n this.tidy(key);\n }\n\n /**\n * The number of active locks. Will always be less or equal to `max`.\n *\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n count(key: string | number = defaultKey): number {\n if (this.hasSemaphoreInstance(key)) {\n return this.getSemaphoreInstance(key).count;\n } else {\n return 0;\n }\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {boolean} True if the semaphore and key has locks, false otherwise.\n */\n hasTasks(key: string | number = defaultKey): boolean {\n return this.count(key) > 0;\n }\n\n /**\n * @param {Function<T>} fn The function to execute.\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {Promise<T>}\n */\n async request<T>(\n fn: Function,\n key: string | number = defaultKey,\n ): Promise<T> {\n try {\n await this.acquire(key);\n return await fn();\n } finally {\n this.release(key);\n }\n }\n\n /**\n * Asynchronously executes `fn` if a lock can be immediately acquired.\n * Otherwise, returns null.\n *\n * @param {Function<T>} fn The function to execute.\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {Promise<T>}\n */\n async requestIfAvailable<T>(\n fn: Function,\n key: string | number = defaultKey,\n ): Promise<T | null> {\n if (this.canAcquire(key)) {\n return this.request(fn, key);\n } else {\n return null;\n }\n }\n\n async wait(key: string | number = defaultKey) {\n if (this.hasTasks(key)) {\n return this.getSemaphoreInstance(key).wait();\n } else {\n return Promise.resolve();\n }\n }\n}\n\nexport default Semaphore;\n"],"names":["SemaphoreItem","constructor","maxConcurrent","this","queue","waitQueue","count","canAcquire","incrementCount","decrementCount","forEach","resolve","acquire","Promise","push","release","resolveFunc","shift","setTimeout","wait","defaultKey","Semaphore","semaphoreInstances","hasSemaphoreInstance","key","Boolean","getSemaphoreInstance","tidy","hasTasks","request","fn","requestIfAvailable"],"mappings":"AAAA,MAAMA,EAUJC,WAAAA,CAAYC,GAAqBC,KATzBC,WAAK,EAAAD,KACLE,eAAS,EAAAF,KACTD,mBAKDI,EAAAA,KAAAA,WAGL,EAAAH,KAAKC,MAAQ,GACbD,KAAKE,UAAY,GACjBF,KAAKD,cAAgBA,EACrBC,KAAKG,MAAQ,CACf,CAEA,cAAIC,GACF,YAAYD,MAAQH,KAAKD,aAC3B,CAEQM,cAAAA,GACNL,KAAKG,OACP,CAEQG,cAAAA,GACNN,KAAKG,QAEc,IAAfH,KAAKG,QACPH,KAAKE,UAAUK,QAASC,GAAYA,KACpCR,KAAKE,UAAY,GAErB,CAEAO,OAAAA,GACE,OAAIT,KAAKI,YACPJ,KAAKK,iBACEK,QAAQF,WAEJ,IAAAE,QAASF,GAAYR,KAAKC,MAAMU,KAAKH,GAEpD,CAEAI,OAAAA,GACE,MAAMC,EAAcb,KAAKC,MAAMa,QAE3BD,EAEFE,WAAWF,EAAa,GAExBb,KAAKM,gBAET,CAEAU,IAAAA,GACE,OAAW,IAAAN,QAASF,GAAYR,KAAKE,UAAUS,KAAKH,GACtD,EAGF,MAAMS,EAAa,WAEnB,MAAMC,EAOJpB,WAAAA,CAAYC,EAAwB,GAN5BoB,KAAAA,wBACApB,EAAAA,KAAAA,qBAMNC,KAAKmB,mBAAqB,GAC1BnB,KAAKD,cAAgBA,CACvB,CAEQqB,oBAAAA,CAAqBC,EAAuBJ,GAClD,OAAOK,QAAQtB,KAAKmB,mBAAmBE,GACzC,CAEQE,oBAAAA,CAAqBF,EAAuBJ,GAIlD,OAHKjB,KAAKoB,qBAAqBC,KAC7BrB,KAAKmB,mBAAmBE,GAAO,IAAIxB,EAAcG,KAAKD,gBAE7CC,KAACmB,mBAAmBE,EACjC,CAKQG,IAAAA,CAAKH,EAAuBJ,GAEhCjB,KAAKoB,qBAAqBC,IACe,IAAzCrB,KAAKuB,qBAAqBF,GAAKlB,cAEpBH,KAACmB,mBAAmBE,EAEnC,CASAjB,UAAAA,CAAWiB,EAAuBJ,GAChC,OAAWjB,KAACuB,qBAAqBF,GAAKjB,UACxC,CAKAK,OAAAA,CAAQY,EAAuBJ,GAC7B,OAAWjB,KAACuB,qBAAqBF,GAAKZ,SACxC,CAKAG,OAAAA,CAAQS,EAAuBJ,GAC7BjB,KAAKuB,qBAAqBF,GAAKT,UAC/BZ,KAAKwB,KAAKH,EACZ,CAOAlB,KAAAA,CAAMkB,EAAuBJ,GAC3B,OAAIjB,KAAKoB,qBAAqBC,GACrBrB,KAAKuB,qBAAqBF,GAAKlB,MAGvC,CACH,CAMAsB,QAAAA,CAASJ,EAAuBJ,GAC9B,OAAOjB,KAAKG,MAAMkB,GAAO,CAC3B,CAOA,aAAMK,CACJC,EACAN,EAAuBJ,GAEvB,IAEE,aADMjB,KAAKS,QAAQY,SACNM,GACd,CAAA,QACC3B,KAAKY,QAAQS,EACd,CACH,CAUA,wBAAMO,CACJD,EACAN,EAAuBJ,GAEvB,OAAIjB,KAAKI,WAAWiB,GACPrB,KAAC0B,QAAQC,EAAIN,GAEjB,IAEX,CAEA,UAAML,CAAKK,EAAuBJ,GAChC,OAAIjB,KAAKyB,SAASJ,GACLrB,KAACuB,qBAAqBF,GAAKL,OAE/BN,QAAQF,SAEnB"}
1
+ {"version":3,"file":"promise-semaphore.modern.js","sources":["../src/index.ts"],"sourcesContent":["class SemaphoreItem {\n private queue: Function[];\n private maxConcurrent: number;\n\n /**\n * The number of locks.\n */\n public count: number;\n\n constructor(maxConcurrent: number) {\n this.queue = [];\n this.maxConcurrent = maxConcurrent;\n this.count = 0;\n }\n\n get canAcquire(): boolean {\n return this.count < this.maxConcurrent;\n }\n\n private incrementCount() {\n this.count++;\n }\n\n private decrementCount() {\n this.count--;\n }\n\n acquire(): Promise<void> {\n if (this.canAcquire) {\n this.incrementCount();\n return Promise.resolve();\n } else {\n return new Promise((resolve) => this.queue.push(resolve));\n }\n }\n\n release(): void {\n const resolveFunc = this.queue.shift();\n\n if (resolveFunc) {\n // Give the micro task queue a small break instead of calling resolveFunc() directly\n setTimeout(resolveFunc, 0);\n } else {\n this.decrementCount();\n }\n }\n}\n\nconst defaultKey = \"_default\";\n\nclass Semaphore {\n private semaphoreInstances: Record<string | number, SemaphoreItem>;\n private maxConcurrent: number;\n\n /**\n * @param {number} [maxConcurrent] The maximum number of concurrent locks.\n */\n constructor(maxConcurrent: number = 1) {\n this.semaphoreInstances = {};\n this.maxConcurrent = maxConcurrent;\n }\n\n private hasSemaphoreInstance(key: string | number = defaultKey) {\n return Boolean(this.semaphoreInstances[key]);\n }\n\n private getSemaphoreInstance(key: string | number = defaultKey) {\n if (!this.hasSemaphoreInstance(key)) {\n this.semaphoreInstances[key] = new SemaphoreItem(this.maxConcurrent);\n }\n return this.semaphoreInstances[key];\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n private tidy(key: string | number = defaultKey): void {\n if (\n this.hasSemaphoreInstance(key) &&\n this.getSemaphoreInstance(key).count === 0\n ) {\n delete this.semaphoreInstances[key];\n }\n }\n\n /**\n * A synchronous function to determine whether a lock can be acquired.\n *\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {boolean} Returns true if the lock on `key` can be acquired, false\n * otherwise.\n */\n canAcquire(key: string | number = defaultKey): boolean {\n return !this.hasSemaphoreInstance(key) ||\n this.getSemaphoreInstance(key).canAcquire;\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n acquire(key: string | number = defaultKey) {\n return this.getSemaphoreInstance(key).acquire();\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n release(key: string | number = defaultKey): void {\n this.getSemaphoreInstance(key).release();\n this.tidy(key);\n }\n\n /**\n * The number of active locks. Will always be less or equal to `max`.\n *\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n count(key: string | number = defaultKey): number {\n if (this.hasSemaphoreInstance(key)) {\n return this.getSemaphoreInstance(key).count;\n } else {\n return 0;\n }\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {boolean} True if the semaphore and key has locks, false otherwise.\n */\n hasTasks(key: string | number = defaultKey): boolean {\n return this.count(key) > 0;\n }\n\n /**\n * @param {Function<T>} fn The function to execute.\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {Promise<T>}\n */\n async request<T>(\n fn: Function,\n key: string | number = defaultKey,\n ): Promise<T> {\n try {\n await this.acquire(key);\n return await fn();\n } finally {\n this.release(key);\n }\n }\n\n /**\n * Asynchronously executes `fn` if a lock can be immediately acquired.\n * Otherwise, returns null.\n *\n * @param {Function<T>} fn The function to execute.\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {Promise<T>}\n */\n async requestIfAvailable<T>(\n fn: Function,\n key: string | number = defaultKey,\n ): Promise<T | null> {\n if (this.canAcquire(key)) {\n return this.request(fn, key);\n } else {\n return null;\n }\n }\n}\n\nexport { Semaphore };\n"],"names":["SemaphoreItem","constructor","maxConcurrent","this","queue","count","canAcquire","incrementCount","decrementCount","acquire","Promise","resolve","push","release","resolveFunc","shift","setTimeout","defaultKey","Semaphore","semaphoreInstances","hasSemaphoreInstance","key","Boolean","getSemaphoreInstance","tidy","hasTasks","request","fn","requestIfAvailable"],"mappings":"AAAA,MAAMA,EASJC,WAAAA,CAAYC,GAAqBC,KARzBC,WAAK,EAAAD,KACLD,mBAAa,EAAAC,KAKdE,WAGL,EAAAF,KAAKC,MAAQ,GACbD,KAAKD,cAAgBA,EACrBC,KAAKE,MAAQ,CACf,CAEA,cAAIC,GACF,OAAOH,KAAKE,MAAQF,KAAKD,aAC3B,CAEQK,cAAAA,GACNJ,KAAKE,OACP,CAEQG,cAAAA,GACNL,KAAKE,OACP,CAEAI,OAAAA,GACE,OAAIN,KAAKG,YACPH,KAAKI,iBACEG,QAAQC,WAER,IAAID,QAASC,GAAYR,KAAKC,MAAMQ,KAAKD,GAEpD,CAEAE,OAAAA,GACE,MAAMC,EAAcX,KAAKC,MAAMW,QAE3BD,EAEFE,WAAWF,EAAa,GAExBX,KAAKK,gBAET,EAGF,MAAMS,EAAa,WAEnB,MAAMC,EAOJjB,WAAAA,CAAYC,EAAwB,GAACC,KAN7BgB,wBAAkB,EAAAhB,KAClBD,mBAAa,EAMnBC,KAAKgB,mBAAqB,CAAA,EAC1BhB,KAAKD,cAAgBA,CACvB,CAEQkB,oBAAAA,CAAqBC,EAAuBJ,GAClD,OAAOK,QAAQnB,KAAKgB,mBAAmBE,GACzC,CAEQE,oBAAAA,CAAqBF,EAAuBJ,GAIlD,OAHKd,KAAKiB,qBAAqBC,KAC7BlB,KAAKgB,mBAAmBE,GAAO,IAAIrB,EAAcG,KAAKD,gBAE7CC,KAACgB,mBAAmBE,EACjC,CAKQG,IAAAA,CAAKH,EAAuBJ,GAEhCd,KAAKiB,qBAAqBC,IACe,IAAzClB,KAAKoB,qBAAqBF,GAAKhB,cAExBF,KAAKgB,mBAAmBE,EAEnC,CASAf,UAAAA,CAAWe,EAAuBJ,GAChC,OAAQd,KAAKiB,qBAAqBC,IAChClB,KAAKoB,qBAAqBF,GAAKf,UACnC,CAKAG,OAAAA,CAAQY,EAAuBJ,GAC7B,OAAWd,KAACoB,qBAAqBF,GAAKZ,SACxC,CAKAI,OAAAA,CAAQQ,EAAuBJ,GAC7Bd,KAAKoB,qBAAqBF,GAAKR,UAC/BV,KAAKqB,KAAKH,EACZ,CAOAhB,KAAAA,CAAMgB,EAAuBJ,GAC3B,OAAId,KAAKiB,qBAAqBC,GACrBlB,KAAKoB,qBAAqBF,GAAKhB,MAGvC,CACH,CAMAoB,QAAAA,CAASJ,EAAuBJ,GAC9B,OAAWd,KAACE,MAAMgB,GAAO,CAC3B,CAOA,aAAMK,CACJC,EACAN,EAAuBJ,GAEvB,IAEE,aADUd,KAACM,QAAQY,SACNM,GACd,CAAA,QACCxB,KAAKU,QAAQQ,EACd,CACH,CAUA,wBAAMO,CACJD,EACAN,EAAuBJ,GAEvB,OAAId,KAAKG,WAAWe,GACPlB,KAACuB,QAAQC,EAAIN,GAEjB,IAEX"}
@@ -1,2 +1,2 @@
1
- function e(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}var t=/*#__PURE__*/function(){function t(e){this.queue=void 0,this.waitQueue=void 0,this.maxConcurrent=void 0,this.count=void 0,this.queue=[],this.waitQueue=[],this.maxConcurrent=e,this.count=0}var n,r,i=t.prototype;return i.incrementCount=function(){this.count++},i.decrementCount=function(){this.count--,0===this.count&&(this.waitQueue.forEach(function(e){return e()}),this.waitQueue=[])},i.acquire=function(){var e=this;return this.canAcquire?(this.incrementCount(),Promise.resolve()):new Promise(function(t){return e.queue.push(t)})},i.release=function(){var e=this.queue.shift();e?setTimeout(e,0):this.decrementCount()},i.wait=function(){var e=this;return new Promise(function(t){return e.waitQueue.push(t)})},n=t,(r=[{key:"canAcquire",get:function(){return this.count<this.maxConcurrent}}])&&function(t,n){for(var r=0;r<n.length;r++){var i=n[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,e(i.key),i)}}(n.prototype,r),Object.defineProperty(n,"prototype",{writable:!1}),n}(),n="_default",r=/*#__PURE__*/function(){function e(e){void 0===e&&(e=1),this.semaphoreInstances=void 0,this.maxConcurrent=void 0,this.semaphoreInstances={},this.maxConcurrent=e}var r=e.prototype;return r.hasSemaphoreInstance=function(e){return void 0===e&&(e=n),Boolean(this.semaphoreInstances[e])},r.getSemaphoreInstance=function(e){return void 0===e&&(e=n),this.hasSemaphoreInstance(e)||(this.semaphoreInstances[e]=new t(this.maxConcurrent)),this.semaphoreInstances[e]},r.tidy=function(e){void 0===e&&(e=n),this.hasSemaphoreInstance(e)&&0===this.getSemaphoreInstance(e).count&&delete this.semaphoreInstances[e]},r.canAcquire=function(e){return void 0===e&&(e=n),this.getSemaphoreInstance(e).canAcquire},r.acquire=function(e){return void 0===e&&(e=n),this.getSemaphoreInstance(e).acquire()},r.release=function(e){void 0===e&&(e=n),this.getSemaphoreInstance(e).release(),this.tidy(e)},r.count=function(e){return void 0===e&&(e=n),this.hasSemaphoreInstance(e)?this.getSemaphoreInstance(e).count:0},r.hasTasks=function(e){return void 0===e&&(e=n),this.count(e)>0},r.request=function(e,t){void 0===t&&(t=n);try{var r=this;return Promise.resolve(function(n,i){try{var o=Promise.resolve(r.acquire(t)).then(function(){return Promise.resolve(e())})}catch(e){return i(!0,e)}return o&&o.then?o.then(i.bind(null,!1),i.bind(null,!0)):i(!1,o)}(0,function(e,n){if(r.release(t),e)throw n;return n}))}catch(e){return Promise.reject(e)}},r.requestIfAvailable=function(e,t){void 0===t&&(t=n);try{return this.canAcquire(t)?Promise.resolve(this.request(e,t)):Promise.resolve(null)}catch(e){return Promise.reject(e)}},r.wait=function(e){void 0===e&&(e=n);try{return this.hasTasks(e)?Promise.resolve(this.getSemaphoreInstance(e).wait()):Promise.resolve()}catch(e){return Promise.reject(e)}},e}();export{r as default};
1
+ function e(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}var t=/*#__PURE__*/function(){function t(e){this.queue=void 0,this.maxConcurrent=void 0,this.count=void 0,this.queue=[],this.maxConcurrent=e,this.count=0}var n,r,i=t.prototype;return i.incrementCount=function(){this.count++},i.decrementCount=function(){this.count--},i.acquire=function(){var e=this;return this.canAcquire?(this.incrementCount(),Promise.resolve()):new Promise(function(t){return e.queue.push(t)})},i.release=function(){var e=this.queue.shift();e?setTimeout(e,0):this.decrementCount()},n=t,(r=[{key:"canAcquire",get:function(){return this.count<this.maxConcurrent}}])&&function(t,n){for(var r=0;r<n.length;r++){var i=n[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,e(i.key),i)}}(n.prototype,r),Object.defineProperty(n,"prototype",{writable:!1}),n}(),n="_default",r=/*#__PURE__*/function(){function e(e){void 0===e&&(e=1),this.semaphoreInstances=void 0,this.maxConcurrent=void 0,this.semaphoreInstances={},this.maxConcurrent=e}var r=e.prototype;return r.hasSemaphoreInstance=function(e){return void 0===e&&(e=n),Boolean(this.semaphoreInstances[e])},r.getSemaphoreInstance=function(e){return void 0===e&&(e=n),this.hasSemaphoreInstance(e)||(this.semaphoreInstances[e]=new t(this.maxConcurrent)),this.semaphoreInstances[e]},r.tidy=function(e){void 0===e&&(e=n),this.hasSemaphoreInstance(e)&&0===this.getSemaphoreInstance(e).count&&delete this.semaphoreInstances[e]},r.canAcquire=function(e){return void 0===e&&(e=n),!this.hasSemaphoreInstance(e)||this.getSemaphoreInstance(e).canAcquire},r.acquire=function(e){return void 0===e&&(e=n),this.getSemaphoreInstance(e).acquire()},r.release=function(e){void 0===e&&(e=n),this.getSemaphoreInstance(e).release(),this.tidy(e)},r.count=function(e){return void 0===e&&(e=n),this.hasSemaphoreInstance(e)?this.getSemaphoreInstance(e).count:0},r.hasTasks=function(e){return void 0===e&&(e=n),this.count(e)>0},r.request=function(e,t){void 0===t&&(t=n);try{var r=this;return Promise.resolve(function(n,i){try{var o=Promise.resolve(r.acquire(t)).then(function(){return Promise.resolve(e())})}catch(e){return i(!0,e)}return o&&o.then?o.then(i.bind(null,!1),i.bind(null,!0)):i(!1,o)}(0,function(e,n){if(r.release(t),e)throw n;return n}))}catch(e){return Promise.reject(e)}},r.requestIfAvailable=function(e,t){void 0===t&&(t=n);try{return this.canAcquire(t)?Promise.resolve(this.request(e,t)):Promise.resolve(null)}catch(e){return Promise.reject(e)}},e}();export{r as Semaphore};
2
2
  //# sourceMappingURL=promise-semaphore.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"promise-semaphore.module.js","sources":["../src/index.ts"],"sourcesContent":["class SemaphoreItem {\n private queue: Array<Function>;\n private waitQueue: Array<Function>;\n private maxConcurrent: number;\n\n /**\n * The number of locks.\n */\n public count: number;\n\n constructor(maxConcurrent: number) {\n this.queue = [];\n this.waitQueue = [];\n this.maxConcurrent = maxConcurrent;\n this.count = 0;\n }\n\n get canAcquire(): boolean {\n return this.count < this.maxConcurrent;\n }\n\n private incrementCount() {\n this.count++;\n }\n\n private decrementCount() {\n this.count--;\n\n if (this.count === 0) {\n this.waitQueue.forEach((resolve) => resolve());\n this.waitQueue = [];\n }\n }\n\n acquire(): Promise<void> {\n if (this.canAcquire) {\n this.incrementCount();\n return Promise.resolve();\n } else {\n return new Promise((resolve) => this.queue.push(resolve));\n }\n }\n\n release(): void {\n const resolveFunc = this.queue.shift();\n\n if (resolveFunc) {\n // Give the micro task queue a small break instead of calling resolveFunc() directly\n setTimeout(resolveFunc, 0);\n } else {\n this.decrementCount();\n }\n }\n\n wait(): Promise<void> {\n return new Promise((resolve) => this.waitQueue.push(resolve));\n }\n}\n\nconst defaultKey = \"_default\";\n\nclass Semaphore {\n private semaphoreInstances: Record<string | number, SemaphoreItem>;\n private maxConcurrent: number;\n\n /**\n * @param {number} [maxConcurrent] The maximum number of concurrent locks.\n */\n constructor(maxConcurrent: number = 1) {\n this.semaphoreInstances = {};\n this.maxConcurrent = maxConcurrent;\n }\n\n private hasSemaphoreInstance(key: string | number = defaultKey) {\n return Boolean(this.semaphoreInstances[key]);\n }\n\n private getSemaphoreInstance(key: string | number = defaultKey) {\n if (!this.hasSemaphoreInstance(key)) {\n this.semaphoreInstances[key] = new SemaphoreItem(this.maxConcurrent);\n }\n return this.semaphoreInstances[key];\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n private tidy(key: string | number = defaultKey): void {\n if (\n this.hasSemaphoreInstance(key) &&\n this.getSemaphoreInstance(key).count === 0\n ) {\n delete this.semaphoreInstances[key];\n }\n }\n\n /**\n * A synchronous function to determine whether a lock can be acquired.\n *\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {boolean} Returns true if the lock on `key` can be acquired, false\n * otherwise.\n */\n canAcquire(key: string | number = defaultKey): boolean {\n return this.getSemaphoreInstance(key).canAcquire;\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n acquire(key: string | number = defaultKey) {\n return this.getSemaphoreInstance(key).acquire();\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n release(key: string | number = defaultKey): void {\n this.getSemaphoreInstance(key).release();\n this.tidy(key);\n }\n\n /**\n * The number of active locks. Will always be less or equal to `max`.\n *\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n count(key: string | number = defaultKey): number {\n if (this.hasSemaphoreInstance(key)) {\n return this.getSemaphoreInstance(key).count;\n } else {\n return 0;\n }\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {boolean} True if the semaphore and key has locks, false otherwise.\n */\n hasTasks(key: string | number = defaultKey): boolean {\n return this.count(key) > 0;\n }\n\n /**\n * @param {Function<T>} fn The function to execute.\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {Promise<T>}\n */\n async request<T>(\n fn: Function,\n key: string | number = defaultKey,\n ): Promise<T> {\n try {\n await this.acquire(key);\n return await fn();\n } finally {\n this.release(key);\n }\n }\n\n /**\n * Asynchronously executes `fn` if a lock can be immediately acquired.\n * Otherwise, returns null.\n *\n * @param {Function<T>} fn The function to execute.\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {Promise<T>}\n */\n async requestIfAvailable<T>(\n fn: Function,\n key: string | number = defaultKey,\n ): Promise<T | null> {\n if (this.canAcquire(key)) {\n return this.request(fn, key);\n } else {\n return null;\n }\n }\n\n async wait(key: string | number = defaultKey) {\n if (this.hasTasks(key)) {\n return this.getSemaphoreInstance(key).wait();\n } else {\n return Promise.resolve();\n }\n }\n}\n\nexport default Semaphore;\n"],"names":["SemaphoreItem","maxConcurrent","queue","waitQueue","count","this","_proto","prototype","incrementCount","decrementCount","forEach","resolve","acquire","_this","canAcquire","Promise","push","release","resolveFunc","shift","setTimeout","wait","_this2","key","get","defaultKey","Semaphore","semaphoreInstances","_proto2","hasSemaphoreInstance","Boolean","getSemaphoreInstance","tidy","hasTasks","request","fn","_this3","then","_finallyRethrows","_wasThrown","_result","e","reject","requestIfAvailable"],"mappings":"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"}
1
+ {"version":3,"file":"promise-semaphore.module.js","sources":["../src/index.ts"],"sourcesContent":["class SemaphoreItem {\n private queue: Function[];\n private maxConcurrent: number;\n\n /**\n * The number of locks.\n */\n public count: number;\n\n constructor(maxConcurrent: number) {\n this.queue = [];\n this.maxConcurrent = maxConcurrent;\n this.count = 0;\n }\n\n get canAcquire(): boolean {\n return this.count < this.maxConcurrent;\n }\n\n private incrementCount() {\n this.count++;\n }\n\n private decrementCount() {\n this.count--;\n }\n\n acquire(): Promise<void> {\n if (this.canAcquire) {\n this.incrementCount();\n return Promise.resolve();\n } else {\n return new Promise((resolve) => this.queue.push(resolve));\n }\n }\n\n release(): void {\n const resolveFunc = this.queue.shift();\n\n if (resolveFunc) {\n // Give the micro task queue a small break instead of calling resolveFunc() directly\n setTimeout(resolveFunc, 0);\n } else {\n this.decrementCount();\n }\n }\n}\n\nconst defaultKey = \"_default\";\n\nclass Semaphore {\n private semaphoreInstances: Record<string | number, SemaphoreItem>;\n private maxConcurrent: number;\n\n /**\n * @param {number} [maxConcurrent] The maximum number of concurrent locks.\n */\n constructor(maxConcurrent: number = 1) {\n this.semaphoreInstances = {};\n this.maxConcurrent = maxConcurrent;\n }\n\n private hasSemaphoreInstance(key: string | number = defaultKey) {\n return Boolean(this.semaphoreInstances[key]);\n }\n\n private getSemaphoreInstance(key: string | number = defaultKey) {\n if (!this.hasSemaphoreInstance(key)) {\n this.semaphoreInstances[key] = new SemaphoreItem(this.maxConcurrent);\n }\n return this.semaphoreInstances[key];\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n private tidy(key: string | number = defaultKey): void {\n if (\n this.hasSemaphoreInstance(key) &&\n this.getSemaphoreInstance(key).count === 0\n ) {\n delete this.semaphoreInstances[key];\n }\n }\n\n /**\n * A synchronous function to determine whether a lock can be acquired.\n *\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {boolean} Returns true if the lock on `key` can be acquired, false\n * otherwise.\n */\n canAcquire(key: string | number = defaultKey): boolean {\n return !this.hasSemaphoreInstance(key) ||\n this.getSemaphoreInstance(key).canAcquire;\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n acquire(key: string | number = defaultKey) {\n return this.getSemaphoreInstance(key).acquire();\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n release(key: string | number = defaultKey): void {\n this.getSemaphoreInstance(key).release();\n this.tidy(key);\n }\n\n /**\n * The number of active locks. Will always be less or equal to `max`.\n *\n * @param {string | number} [key]- Optional, the semaphore key.\n */\n count(key: string | number = defaultKey): number {\n if (this.hasSemaphoreInstance(key)) {\n return this.getSemaphoreInstance(key).count;\n } else {\n return 0;\n }\n }\n\n /**\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {boolean} True if the semaphore and key has locks, false otherwise.\n */\n hasTasks(key: string | number = defaultKey): boolean {\n return this.count(key) > 0;\n }\n\n /**\n * @param {Function<T>} fn The function to execute.\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {Promise<T>}\n */\n async request<T>(\n fn: Function,\n key: string | number = defaultKey,\n ): Promise<T> {\n try {\n await this.acquire(key);\n return await fn();\n } finally {\n this.release(key);\n }\n }\n\n /**\n * Asynchronously executes `fn` if a lock can be immediately acquired.\n * Otherwise, returns null.\n *\n * @param {Function<T>} fn The function to execute.\n * @param {string | number} [key]- Optional, the semaphore key.\n * @returns {Promise<T>}\n */\n async requestIfAvailable<T>(\n fn: Function,\n key: string | number = defaultKey,\n ): Promise<T | null> {\n if (this.canAcquire(key)) {\n return this.request(fn, key);\n } else {\n return null;\n }\n }\n}\n\nexport { Semaphore };\n"],"names":["SemaphoreItem","maxConcurrent","queue","this","count","_proto","prototype","incrementCount","decrementCount","acquire","_this","canAcquire","Promise","resolve","push","release","resolveFunc","shift","setTimeout","key","get","defaultKey","Semaphore","semaphoreInstances","_proto2","hasSemaphoreInstance","Boolean","getSemaphoreInstance","tidy","hasTasks","request","fn","_this2","then","_finallyRethrows","_wasThrown","_result","e","reject","requestIfAvailable"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chriscdn/promise-semaphore",
3
- "version": "2.0.11",
3
+ "version": "3.0.0",
4
4
  "description": "Limit or throttle the simultaneous execution of asynchronous code in separate iterations of the event loop.",
5
5
  "repository": "https://github.com/chriscdn/promise-semaphore",
6
6
  "author": "Christopher Meyer <chris@schwiiz.org>",
package/src/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  class SemaphoreItem {
2
- private queue: Array<Function>;
3
- private waitQueue: Array<Function>;
2
+ private queue: Function[];
4
3
  private maxConcurrent: number;
5
4
 
6
5
  /**
@@ -10,7 +9,6 @@ class SemaphoreItem {
10
9
 
11
10
  constructor(maxConcurrent: number) {
12
11
  this.queue = [];
13
- this.waitQueue = [];
14
12
  this.maxConcurrent = maxConcurrent;
15
13
  this.count = 0;
16
14
  }
@@ -25,11 +23,6 @@ class SemaphoreItem {
25
23
 
26
24
  private decrementCount() {
27
25
  this.count--;
28
-
29
- if (this.count === 0) {
30
- this.waitQueue.forEach((resolve) => resolve());
31
- this.waitQueue = [];
32
- }
33
26
  }
34
27
 
35
28
  acquire(): Promise<void> {
@@ -51,10 +44,6 @@ class SemaphoreItem {
51
44
  this.decrementCount();
52
45
  }
53
46
  }
54
-
55
- wait(): Promise<void> {
56
- return new Promise((resolve) => this.waitQueue.push(resolve));
57
- }
58
47
  }
59
48
 
60
49
  const defaultKey = "_default";
@@ -102,7 +91,8 @@ class Semaphore {
102
91
  * otherwise.
103
92
  */
104
93
  canAcquire(key: string | number = defaultKey): boolean {
105
- return this.getSemaphoreInstance(key).canAcquire;
94
+ return !this.hasSemaphoreInstance(key) ||
95
+ this.getSemaphoreInstance(key).canAcquire;
106
96
  }
107
97
 
108
98
  /**
@@ -176,14 +166,6 @@ class Semaphore {
176
166
  return null;
177
167
  }
178
168
  }
179
-
180
- async wait(key: string | number = defaultKey) {
181
- if (this.hasTasks(key)) {
182
- return this.getSemaphoreInstance(key).wait();
183
- } else {
184
- return Promise.resolve();
185
- }
186
- }
187
169
  }
188
170
 
189
- export default Semaphore;
171
+ export { Semaphore };