Swimmer

1.4.0 · abandoned · verified Sun Apr 19

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.

Common errors

Warnings

Install

Imports

Quickstart

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.

import { createPool } from 'swimmer';

const urlsToProcess = [
  'https://api.example.com/data/1',
  'https://api.example.com/data/2',
  'https://api.example.com/data/3',
  'https://api.example.com/data/4',
  'https://api.example.com/data/5',
  'https://api.example.com/data/6',
  'https://api.example.com/data/7',
  'https://api.example.com/data/8'
];

// Create a new pool with a concurrency limit of 3
const dataPool = createPool({
  concurrency: 3,
  tasks: urlsToProcess.slice(0, 3).map(url => () => fetch(url).then(res => res.json()))
});

// Subscribe to successful task completions
dataPool.onSuccess((result, taskFn) => {
  console.log(`Task successful. Result: ${JSON.stringify(result).substring(0, 50)}...`);
});

// Subscribe to errors, re-adding failed tasks for retry
dataPool.onError((err, taskFn) => {
  console.error(`Task failed: ${err.message}. Re-adding to pool for retry.`);
  dataPool.add(taskFn);
});

// Subscribe when the entire pool is settled (all tasks finished or retried)
dataPool.onSettled(() => {
  console.log('All tasks in the pool have settled.');
});

const startProcessing = async () => {
  console.log('Starting data processing with Swimmer pool...');

  // Add remaining tasks to the pool
  urlsToProcess.slice(3).forEach(url => {
    dataPool.add(() => fetch(url).then(res => res.json()));
  });

  // Dynamically adjust concurrency
  console.log('Increasing concurrency to 5.');
  dataPool.throttle(5);

  // Add a critical task and wait for its immediate completion/failure
  try {
    const singleResult = await dataPool.add(() => fetch('https://api.example.com/critical-data').then(res => res.json()));
    console.log('Critical task completed:', JSON.stringify(singleResult).substring(0, 50), '...');
  } catch (error) {
    console.error('Critical task failed:', error.message);
  }

  // The pool will continue processing until all tasks are done or explicitly cleared.
  // For demonstration, we'll let it run.
};

// Simulate API calls with a delay
const originalFetch = global.fetch;
global.fetch = async (url) => {
  const delay = Math.random() * 500 + 100; // 100ms to 600ms delay
  await new Promise(resolve => setTimeout(resolve, delay));
  if (Math.random() < 0.1) { // 10% chance of failure
    throw new Error(`Failed to fetch ${url}`);
  }
  return { json: () => Promise.resolve({ source: url, data: 'some_payload', timestamp: Date.now() }) };
};

startProcessing().finally(() => {
  // Restore original fetch after the demonstration
  global.fetch = originalFetch;
});

view raw JSON →