{"_id":"@anders94/throttle","_rev":"3-4611998b0ee3e51ad9168263708fd1a5","name":"@anders94/throttle","dist-tags":{"latest":"2.0.0"},"versions":{"1.0.0":{"name":"@anders94/throttle","version":"1.0.0","keywords":["limit","parallel","execution"],"author":{"name":"Anders Brownworth"},"license":"MIT","_id":"@anders94/throttle@1.0.0","maintainers":[{"name":"anders94","email":"anders-npmjs@evantide.com"}],"homepage":"https://github.com/anders94/throttle#readme","bugs":{"url":"https://github.com/anders94/throttle/issues"},"dist":{"shasum":"a08076673947dc0945a52b051e124e916fa6b78c","tarball":"https://registry.npmjs.org/@anders94/throttle/-/throttle-1.0.0.tgz","fileCount":4,"integrity":"sha512-tPH789sZ9OEPFPGmQdCgK5MnM/E6H7dYwINxM117nVB92wllz2cHVwF7B5mnrlKrq1/9ce4cgZy1KG7L2nCHBQ==","signatures":[{"sig":"MEYCIQDwaU3k5UcH+4oszY6jrnl17PxCcMfsXNr0Z50qgO/t6AIhAIZjpEk2eZB7Oc8g+LgSr3lUiJTgC7EZsLAaN2C8WbcR","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":3317},"main":"index.js","gitHead":"98d0332e328a1c5f1b2bd8fcfa2f19bf98ac4bac","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"_npmUser":{"name":"anders94","email":"anders-npmjs@evantide.com"},"repository":{"url":"git+https://github.com/anders94/throttle.git","type":"git"},"_npmVersion":"10.8.3","description":"Parallelize function execution up to a defined limit.","directories":{},"_nodeVersion":"20.12.2","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/throttle_1.0.0_1725561132234_0.4063066192314526","host":"s3://npm-registry-packages"}},"1.0.1":{"name":"@anders94/throttle","version":"1.0.1","keywords":["limit","parallel","execution"],"author":{"name":"Anders Brownworth"},"license":"MIT","_id":"@anders94/throttle@1.0.1","maintainers":[{"name":"anders94","email":"anders-npmjs@evantide.com"}],"homepage":"https://github.com/anders94/throttle#readme","bugs":{"url":"https://github.com/anders94/throttle/issues"},"dist":{"shasum":"17cf2d00fdc7a9cf74392e248a3a2165d8c2eb79","tarball":"https://registry.npmjs.org/@anders94/throttle/-/throttle-1.0.1.tgz","fileCount":4,"integrity":"sha512-ICsjKIiRvotoXbc868E6xje/AMpB6t1/qX/m+YxQ7GjpWW69EfB3KVndsfL0SmFM4dQH5Wmp7jVwp6eHDALnCQ==","signatures":[{"sig":"MEQCIHlf6xVI73m9uAQwreSF2Oc0NcN+rcwTJ3Wcv8Vt3hZHAiBdCTrjQ+YMVhSqYAOjGUl4tg23ODI1/Iom41bIbSN80A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":6943},"main":"index.js","gitHead":"d6f77db38b3ad75badff188ee18f040416715c68","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"_npmUser":{"name":"anders94","email":"anders-npmjs@evantide.com"},"repository":{"url":"git+https://github.com/anders94/throttle.git","type":"git"},"_npmVersion":"11.4.2","description":"Parallelize function execution up to a defined limit.","directories":{},"_nodeVersion":"24.4.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/throttle_1.0.1_1758980981807_0.8801305384578053","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@anders94/throttle","version":"2.0.0","description":"Parallelize function execution up to a defined limit.","main":"index.js","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"repository":{"type":"git","url":"git+https://github.com/anders94/throttle.git"},"keywords":["limit","parallel","execution"],"author":{"name":"Anders Brownworth"},"license":"MIT","bugs":{"url":"https://github.com/anders94/throttle/issues"},"homepage":"https://github.com/anders94/throttle#readme","_id":"@anders94/throttle@2.0.0","gitHead":"45ff51dedb47ede7176f32d8ed8a79f1a34bd2d5","_nodeVersion":"24.4.1","_npmVersion":"11.4.2","dist":{"integrity":"sha512-+3Hr8DoIPVzkICw3rFd6s6LORyiCNlZ/Z0KXfM1tcD2gVFsDOuVEknj7rxROJKb+mSIB/QjS2Y/iyNXaxogCew==","shasum":"db0f6d84920685ff0933c7b0e9f58bbca834642d","tarball":"https://registry.npmjs.org/@anders94/throttle/-/throttle-2.0.0.tgz","fileCount":5,"unpackedSize":9280,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIG3OkGePBYM4FotFh0VMZyC8npxrOpO2NMVZLFklXE3RAiAOxQQ0iahDdflIcGNPcYINwkg8nh+dBJ9P/Ci3Wkrk+A=="}]},"_npmUser":{"name":"anders94","email":"anders-npmjs@evantide.com"},"directories":{},"maintainers":[{"name":"anders94","email":"anders-npmjs@evantide.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/throttle_2.0.0_1760759337330_0.8081497862577478"},"_hasShrinkwrap":false}},"time":{"created":"2024-09-05T18:32:12.105Z","modified":"2025-10-18T03:48:57.706Z","1.0.0":"2024-09-05T18:32:12.411Z","1.0.1":"2025-09-27T13:49:42.034Z","2.0.0":"2025-10-18T03:48:57.524Z"},"bugs":{"url":"https://github.com/anders94/throttle/issues"},"author":{"name":"Anders Brownworth"},"license":"MIT","homepage":"https://github.com/anders94/throttle#readme","keywords":["limit","parallel","execution"],"repository":{"type":"git","url":"git+https://github.com/anders94/throttle.git"},"description":"Parallelize function execution up to a defined limit.","maintainers":[{"name":"anders94","email":"anders-npmjs@evantide.com"}],"readme":"throttle\n========\nParallelize function execution in Node.js up to a defined limit.\n\nUsually you either run functions one after the other sequentially or in parallel\nsimultaneously. However, many times it would be more helpful to run up to some\nnumber of parallelized functions but fall back to serial beyond that. This Node.js\nmodule provides a framework for this.\n\n## Install\n```sh\nnpm i @anders94/throttle\n```\n\n## Quick Start\nOnce you `enqueue()` functions, they immediately start to execute.\n\n```js\nconst Throttle = require('@anders94/throttle');\n\nconst throttle = new Throttle(2);\n\n// wrap setTimeout in a promise\nconst timeout = (ms) => {\n    return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nconst wait = async (delay) => {\n    console.log('start', delay, 'ms timer.');\n    await timeout(delay);\n    console.log('end', delay, 'ms timer.');\n\n}\n\nawait Promise.all([\n    throttle.enqueue(async () => await wait(400)),\n    throttle.enqueue(async () => await wait(300)),\n    throttle.enqueue(async () => await wait(200)),\n    throttle.enqueue(async () => await wait(100))\n]);\nconsole.log('All functions completed!');\n```\n\nIn the above example, `const throttle = new Throttle(2)` initialized the throttle\nto run up to `2` functions at the same time. We quickly enqueued 4 functions, each\nwaiting less and less time, so the first two start (`wait 400ms` and `wait 300ms`) but\nthe next two are enqueued but don't start executing. The first to finish is the\nsecond function, (`wait 300ms`) so `wait 200ms` starts. Next to finish is the first\nfunction, (`wait 400ms`) so `wait 100ms` starts next which ends soon after. Last\nto end is `wait 200ms`.\n\n**Output:**\n```\nstart 400 ms timer.\nstart 300 ms timer.\nend 300 ms timer.\nstart 200 ms timer.\nend 400 ms timer.\nstart 100 ms timer.\nend 100 ms timer.\nend 200 ms timer.\n```\n\n## API Reference\n\n### Constructor\n\n#### `new Throttle(limit)`\nCreates a new throttle instance.\n\n- **limit** `{number}` - Maximum number of functions to run concurrently. Default: `2`\n\n**Example:**\n```js\nconst throttle = new Throttle(3); // Allow up to 3 concurrent functions\n```\n\n### Methods\n\n#### `enqueue(fn)`\nAdds a function to the execution queue. If there are available execution slots (below the limit), the function starts immediately. Otherwise, it waits in the queue.\n\n- **fn** `{function}` - Function to execute (can be sync or async)\n- **Returns:** `{Promise}` - Promise that resolves with the function's return value or rejects with any error thrown\n\n**Example:**\n```js\n// Basic usage with promise\nconst result = await throttle.enqueue(() => 'Hello World');\nconsole.log(result); // 'Hello World'\n\n// With async functions\nconst data = await throttle.enqueue(async () => {\n    const response = await fetch('https://api.example.com/data');\n    return response.json();\n});\n\n// Error handling\ntry {\n    await throttle.enqueue(() => {\n        throw new Error('Something went wrong');\n    });\n} catch (error) {\n    console.error(error.message); // 'Something went wrong'\n}\n```\n\n#### `dequeue()`\nRemoves and returns the next task from the queue without executing it.\n\n- **Returns:** `{object|undefined}` - The next queued task object containing `{fn, resolve, reject}`, or `undefined` if queue is empty\n\n**Example:**\n```js\nconst nextTask = throttle.dequeue();\nif (nextTask) {\n    console.log('Dequeued a task');\n    // Note: Manual execution would require calling nextTask.fn() and handling nextTask.resolve/reject\n}\n```\n\n#### `isEmpty()`\nChecks if the queue is empty.\n\n- **Returns:** `{boolean}` - `true` if no functions are queued, `false` otherwise\n\n**Example:**\n```js\nif (!throttle.isEmpty()) {\n    console.log('Still have functions waiting');\n}\n```\n\n#### `length()`\nReturns the number of functions currently in the queue (waiting to execute).\n\n- **Returns:** `{number}` - Number of queued functions\n\n**Example:**\n```js\nconsole.log(`${throttle.length()} functions waiting in queue`);\n```\n\n#### `clearQueue()`\nRemoves all pending functions from the queue and rejects their promises. Does not affect currently running functions.\n\n- **Returns:** `{number}` - Number of tasks that were cleared from the queue\n\n**Example:**\n```js\n// Add some functions to the queue\nthrottle.enqueue(() => 'task 1').catch(err => console.log('Cleared:', err.message));\nthrottle.enqueue(() => 'task 2').catch(err => console.log('Cleared:', err.message));\n\n// Clear all pending tasks\nconst cleared = throttle.clearQueue();\nconsole.log(`${cleared} tasks were cleared`); // \"2 tasks were cleared\"\n```\n\n#### `finish()`\nCalled when the queue becomes empty and all functions have completed. Currently a no-op but can be overridden.\n\n- **Returns:** `undefined`\n\n**Example:**\n```js\nthrottle.finish = () => {\n    console.log('All functions completed!');\n};\n```\n\n### Properties\n\n#### `limit`\nThe maximum number of functions that can run concurrently.\n\n**Example:**\n```js\nconsole.log(`Current limit: ${throttle.limit}`);\nthrottle.limit = 5; // Change the limit dynamically\n```\n\n#### `running`\nThe number of functions currently executing.\n\n**Example:**\n```js\nconsole.log(`${throttle.running} functions currently running`);\n```\n\n## Advanced Usage\n\n### Error Handling\nFunctions that throw errors will reject their returned promise but won't stop the queue. The error is contained to that specific function:\n\n```js\n// This will reject the promise but not affect other functions\nthrottle.enqueue(async () => {\n    throw new Error('This will not stop the queue');\n}).catch(error => {\n    console.error('Function failed:', error.message);\n});\n\n// This will still execute normally\nthrottle.enqueue(() => {\n    console.log('This will still execute');\n}).then(result => {\n    console.log('Function completed successfully');\n});\n```\n\n### Monitoring Queue Status\nYou can monitor the throttle state in real-time:\n\n```js\nconst logStatus = () => {\n    console.log(`Running: ${throttle.running}, Queued: ${throttle.length()}`);\n};\n\nthrottle.enqueue(() => logStatus());\nthrottle.enqueue(() => logStatus());\nthrottle.enqueue(() => logStatus());\n```\n\n### Custom Completion Handling\nOverride the `finish()` method to handle queue completion:\n\n```js\nthrottle.finish = () => {\n    console.log('All tasks completed successfully!');\n    process.exit(0);\n};\n```\n\n### Queue Cleanup\nUse `clearQueue()` for cleanup scenarios like application shutdown:\n\n```js\n// Graceful shutdown\nprocess.on('SIGTERM', () => {\n    console.log('Shutting down...');\n    const cleared = throttle.clearQueue();\n    console.log(`Cancelled ${cleared} pending tasks`);\n    process.exit(0);\n});\n```\n\n## License\nMIT\n","readmeFilename":"README.md"}