npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

concurrency.libx.js

v1.3.1

Published

The missing piece for Async programming

Readme

Node.js CI

᭟ concurrency.libx.js

Helper functions to deal better with multi-concurrency, parallelism and promises.
This lib is browser compatible, and nodejs environment.

Features:

  • The missing piece in asynchronous programming - Leverage Promises by manually creating Deferred object (like Promise but with more control).
  • Advanced utils for concurrent events - Throttle, debounce, chain and more.
  • Easily convert synchronous functions to asynchronous - Dynamically convert functions to async functions.

Use:

NodeJS:

yarn add concurrency.libx.js

Check more examples in unit-test at tests.

Browser:

https://cdn.jsdelivr.net/npm/concurrency.libx.js@latest/dist/browser.min.js
(Modules are loaded into `window.libx.concurrency` object).

Use this library in browser from CDN, code example, live example.
Or include from node_modules.


Helpers:

-Deferred
-Async
-IsAsync
-Debounce
-Throttle
-Chain
-Delay
-Sleep
-Measurements
-WaitUntil


Deferred:

Create promises as an object to manually wrap non-promisified functions and avoid callback-hell.

New in vNext:

  • Supports progress reporting via both onProgress callback and async iterator (for await...of).
  • Requires ES2018+ for async iterator and Promise.finally support.

Progress Reporting (onProgress)

const { Deferred } = require('concurrency.libx.js');
const d = Deferred.new();
d.onProgress((progress) => {
  console.log('Progress:', progress);
});
d.reportProgress(0.1);
d.reportProgress(0.5);
d.resolve('done');

Progress Reporting (Async Iterator)

const d = Deferred.new();
(async () => {
  for await (const progress of d) {
    console.log('Progress (iterator):', progress);
  }
  console.log('Progress stream ended');
})();
d.reportProgress(0.1);
d.reportProgress(0.5);
d.resolve('done');

While util.promisify is useful to convert callback-based functions to promisibable functions, concurrency.libx.js is useful to manually manage resolve and reject operations.

Instead:

const util = require('util');
const fs = require('fs');
const stat = util.promisify(fs.stat);

stat('.').then((stats) => {
	// Do something with `stats`
}).catch((error) => {
	// Handle the error.
});

// or
async function callStat() {
	const stats = await stat('.');
	console.log(`This directory is owned by ${stats.uid}`);
}

Do:

const fs = require('fs');
const { Deferred } = require('concurrency.libx.js');
const p = Deferred.new();

fs.stat('.', (err, value)=> {
	if (err) return p.reject(err);
	p.resolve(value);
})

(async()=>{
	const stat = await p;
})();

This approach allows easier to turn deep callback-based functions, spaghetti or legacy code, into more modern promisiable code with fewer changes.

concurrency.libx.js is also browser friendly and supports node versions before 8.

Async:

Dynamically make a sync function async and return a promise. It'll wrap your function with a promise and will allow you treat synchronous functions as asyncs, dynamically.

import { async } from 'concurrency.libx.js';
let syncFunc = (arg) => { // synchronous function
	counter = arg;
	return 10;
}
let result = await async(syncFunc); // call it as if it was asynchronous

IsAsync:

Determin dynamically if a given function is async or not.

import { isAsync } from 'concurrency.libx.js';
isAsync((x)=>x=1); // false
isAsync(async (x)=>x=1); // true

Debounce:

Make a function that is expected to be called multiple times, to be spread with even intervals. Does not skip any call, just delays them.

import { debounce } from 'concurrency.libx.js';
let func = debounce(()=>{
	setInterval(()=>console.log('x'), 10);
}, 100;
func(); // Will make the function to be called with 100ms between each call.

Throttle:

Make a function that is expected to be called multiple times, to be called only once in a given interval. Will skip calls in between.

import { throttle } from 'concurrency.libx.js';
let func = throttle(()=>{
	setInterval(()=>console.log('x'), 10);
}, 20, true);
func(); // The function will be called only once per 20ms, each time one call will be ignored.

Chain:

Perform a given array of async functions in a sequence.

import { chain } from 'concurrency.libx.js';
let tasks = [async ()=>console.log(1), async ()=>console.log(2)];
await chain.chainTasks(tasks);

Delay:

Let the JS VM continue treating other stuff and get back to your block after period passed.
Same as setting setTimeout(fun, dur) but with avoiding the callback-hell;

import { delay } from 'concurrency.libx.js';
console.log('before');
await delay(100);
console.log('after 100ms');

Sleep:

Basically the same as delay, just uses Promise object instead Deferred.

import { sleep } from 'concurrency.libx.js';
await sleep(100);

Measurements:

Helper functions to measure execution times.

import { measurements } from 'concurrency.libx.js';
measurements.startMeasure('test');
await delay(100);
let duration = measurements.peekMeasure('test2');
let duration = measurements.startMeasure('test');

// or:
let duration = measurements.measure(async ()=>{
	await delay(100);
});

WaitUntil:

Pass a condition and let this helper check periodically for you until the condition is met. You can use then or await to respond to the completion.

import { waitUntil } from 'concurrency.libx.js';
let counter = 0;
let condition = ()=> counter == 10;
setInterval(()=> counter++, 500); // Will progress in parallel to `waitUntil`
let interval = 10; // How often to run the condition check
await waitUntil(condition, ()=> {
	console.log('condition reached!');
}, interval);

Develop:

Build:

$ yarn build

Watch & Build:

$ yarn watch

Run tests:

$ yarn test