{"id":12109,"library":"swimmer","title":"Swimmer","description":"Swimmer is a lightweight JavaScript utility for async task pooling and throttling. It provides two main APIs: `poolAll` for inline, promise-based concurrency control, and `createPool` for more advanced, reusable pools with configurable concurrency, error handling, and lifecycle events like `onSuccess`, `onError`, and `onSettled`. The library is designed to be simple to use, ES6 and async/await ready, and has zero external dependencies, making it a 3kb addition to projects. While effective for its stated purpose, the package (version 1.4.0) has not seen active development since its last update around August 2018, and its primary author has moved on to other projects. Therefore, new features, bug fixes, or security patches are unlikely.","status":"abandoned","version":"1.4.0","language":"javascript","source_language":"en","source_url":"https://github.com/tannerlinsley/swimmer","tags":["javascript"],"install":[{"cmd":"npm install swimmer","lang":"bash","label":"npm"},{"cmd":"yarn add swimmer","lang":"bash","label":"yarn"},{"cmd":"pnpm add swimmer","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Primarily designed for ESM usage with `import`. While CommonJS `require` might work in some environments, ESM is the intended and idiomatic usage based on the documentation.","wrong":"const { poolAll } = require('swimmer')","symbol":"poolAll","correct":"import { poolAll } from 'swimmer'"},{"note":"Use named import for `createPool` to access the custom pooling API. Similar to `poolAll`, ESM `import` is the documented approach.","wrong":"const createPool = require('swimmer').createPool","symbol":"createPool","correct":"import { createPool } from 'swimmer'"},{"note":"The `createPool` function returns a Pool instance with methods like `add`, `start`, `stop`, `throttle`, `onError`, `onSuccess`, etc. These methods are accessed directly on the returned object.","symbol":"PoolInstance","correct":"const pool = createPool(...); pool.add(...)"}],"quickstart":{"code":"import { createPool } from 'swimmer';\n\nconst urlsToProcess = [\n  'https://api.example.com/data/1',\n  'https://api.example.com/data/2',\n  'https://api.example.com/data/3',\n  'https://api.example.com/data/4',\n  'https://api.example.com/data/5',\n  'https://api.example.com/data/6',\n  'https://api.example.com/data/7',\n  'https://api.example.com/data/8'\n];\n\n// Create a new pool with a concurrency limit of 3\nconst dataPool = createPool({\n  concurrency: 3,\n  tasks: urlsToProcess.slice(0, 3).map(url => () => fetch(url).then(res => res.json()))\n});\n\n// Subscribe to successful task completions\ndataPool.onSuccess((result, taskFn) => {\n  console.log(`Task successful. Result: ${JSON.stringify(result).substring(0, 50)}...`);\n});\n\n// Subscribe to errors, re-adding failed tasks for retry\ndataPool.onError((err, taskFn) => {\n  console.error(`Task failed: ${err.message}. Re-adding to pool for retry.`);\n  dataPool.add(taskFn);\n});\n\n// Subscribe when the entire pool is settled (all tasks finished or retried)\ndataPool.onSettled(() => {\n  console.log('All tasks in the pool have settled.');\n});\n\nconst startProcessing = async () => {\n  console.log('Starting data processing with Swimmer pool...');\n\n  // Add remaining tasks to the pool\n  urlsToProcess.slice(3).forEach(url => {\n    dataPool.add(() => fetch(url).then(res => res.json()));\n  });\n\n  // Dynamically adjust concurrency\n  console.log('Increasing concurrency to 5.');\n  dataPool.throttle(5);\n\n  // Add a critical task and wait for its immediate completion/failure\n  try {\n    const singleResult = await dataPool.add(() => fetch('https://api.example.com/critical-data').then(res => res.json()));\n    console.log('Critical task completed:', JSON.stringify(singleResult).substring(0, 50), '...');\n  } catch (error) {\n    console.error('Critical task failed:', error.message);\n  }\n\n  // The pool will continue processing until all tasks are done or explicitly cleared.\n  // For demonstration, we'll let it run.\n};\n\n// Simulate API calls with a delay\nconst originalFetch = global.fetch;\nglobal.fetch = async (url) => {\n  const delay = Math.random() * 500 + 100; // 100ms to 600ms delay\n  await new Promise(resolve => setTimeout(resolve, delay));\n  if (Math.random() < 0.1) { // 10% chance of failure\n    throw new Error(`Failed to fetch ${url}`);\n  }\n  return { json: () => Promise.resolve({ source: url, data: 'some_payload', timestamp: Date.now() }) };\n};\n\nstartProcessing().finally(() => {\n  // Restore original fetch after the demonstration\n  global.fetch = originalFetch;\n});","lang":"javascript","description":"This example demonstrates how to create and manage a custom task pool using `createPool`, handle successes and errors with callbacks, dynamically adjust concurrency, and add tasks, including waiting for individual task completion."},"warnings":[{"fix":"For new projects, consider alternative, actively maintained libraries for async task management or implement custom pooling logic. For existing projects, be aware of the lack of future updates and potential security vulnerabilities.","message":"Swimmer is no longer actively maintained. The last release (v1.4.0) was published in August 2018, and its primary author has moved on to other projects. This means there will be no new features, bug fixes, or security updates. Users should consider this carefully for long-term projects or those requiring ongoing support.","severity":"breaking","affected_versions":">=1.4.0"},{"fix":"If 'fail-fast' is not desired, use `createPool` instead. The custom pool allows you to subscribe to individual `onError` events and implement custom retry logic or simply log the error and allow other tasks to continue.","message":"When using `poolAll`, any error encountered by a single task will immediately stop the entire pool and throw the error. This 'fail-fast' behavior might not be desired if you want other tasks to complete even if some fail.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always wrap your promise-returning logic in a function. Correct: `() => fetch(url)`. Incorrect: `fetch(url)`.","message":"Tasks passed to `poolAll` or `pool.add` must be 'thunks' – functions that return a promise, not the promise itself. Passing an already-fired promise means Swimmer cannot manage its lifecycle.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure you are using `import { poolAll } from 'swimmer'` in an ES module context or if using CommonJS, `const swimmer = require('swimmer'); const poolAll = swimmer.poolAll;` might be necessary, though inconsistent with documentation. Verify your build configuration for ESM/CJS transpilation.","cause":"This typically occurs in CommonJS environments when `swimmer` is imported using `require()` but treated as an ES module or when bundling tools incorrectly handle the export. The library was released before widespread native ESM support in Node.js.","error":"TypeError: (0 , _swimmer.poolAll) is not a function"},{"fix":"For `poolAll`, always wrap the call in a `try...catch` block: `try { await poolAll(...) } catch (err) { ... }`. For `createPool`, register an error handler: `pool.onError((err, task) => { console.error(err); });`.","cause":"If a task within `poolAll` or `createPool` rejects, and you haven't attached a `.catch()` handler to the `poolAll` call or registered an `onError` callback for `createPool`, the promise rejection will go unhandled.","error":"UnhandledPromiseRejectionWarning: A promise was rejected with a reason that was not handled"},{"fix":"Ensure that every function you provide to Swimmer's pooling mechanism (e.g., in `urls.map(task => () => fetch(url))`) explicitly returns a Promise. The task itself should be a function that, when called, produces a Promise.","cause":"This error arises when a function passed as a task to `poolAll` or `pool.add` does not return a Promise or a thenable object.","error":"TypeError: task.then is not a function"}],"ecosystem":"npm"}