All Projects → charto → Cwait

charto / Cwait

Licence: mit
⌛️ Limit number of promises running in parallel

Programming Languages

typescript
32286 projects

Labels

Projects that are alternatives of or similar to Cwait

Mux
Creates a promise that waits for the promises in nested data structures and resolves to data structures of the same form. It recursively traverses the input data structure and multiplexes its promises.
Stars: ✭ 153 (-16.85%)
Mutual labels:  promise
Async Busboy
Promise based multipart form parser for KoaJS
Stars: ✭ 159 (-13.59%)
Mutual labels:  promise
Load Google Maps Api
🌏 A lightweight Promise-returning helper for loading the Google Maps JavaScript API
Stars: ✭ 166 (-9.78%)
Mutual labels:  promise
Angular Promise Buttons
Chilled loading buttons for AngularJS
Stars: ✭ 156 (-15.22%)
Mutual labels:  promise
Es6
ES5 vs ES6 Reference
Stars: ✭ 158 (-14.13%)
Mutual labels:  promise
Next Session
Simple promise-based session middleware for Next.js, micro, Express, and more
Stars: ✭ 161 (-12.5%)
Mutual labels:  promise
Vue Prom
Vue promise wrapper component
Stars: ✭ 148 (-19.57%)
Mutual labels:  promise
Apisauce
Axios + standardized errors + request/response transforms.
Stars: ✭ 2,303 (+1151.63%)
Mutual labels:  promise
React Boilerplate
A slightly opinionated yet dead simple boilerplate for React 17.x, Webpack 5 and React Router v5
Stars: ✭ 158 (-14.13%)
Mutual labels:  promise
Kitsu
🦊 A simple, lightweight & framework agnostic JSON:API client
Stars: ✭ 166 (-9.78%)
Mutual labels:  promise
Foy
A simple, light-weight and modern task runner for general purpose.
Stars: ✭ 157 (-14.67%)
Mutual labels:  promise
Dynasty
Dynasty - Promise-based, clean DynamoDB API
Stars: ✭ 157 (-14.67%)
Mutual labels:  promise
Metasync
Asynchronous Programming Library for JavaScript & Node.js
Stars: ✭ 164 (-10.87%)
Mutual labels:  promise
Mande
600 bytes convenient and modern wrapper around fetch
Stars: ✭ 154 (-16.3%)
Mutual labels:  promise
Scramjet
Simple yet powerful live data computation framework
Stars: ✭ 171 (-7.07%)
Mutual labels:  promise
Promise
Promise / Future library for Go
Stars: ✭ 149 (-19.02%)
Mutual labels:  promise
Ewa
Enhanced Wechat App Development Toolkit (微信小程序增强开发工具)。不同于 wepy 或者 mpvue,是一个轻量级小程序开发框架。支持原生小程序所有功能,无需学习,极易上手。支持转换为百度/字节跳动/QQ小程序。
Stars: ✭ 160 (-13.04%)
Mutual labels:  promise
Fluture
🦋 Fantasy Land compliant (monadic) alternative to Promises
Stars: ✭ 2,249 (+1122.28%)
Mutual labels:  promise
Q
A platform-independent promise library for C++, implementing asynchronous continuations.
Stars: ✭ 179 (-2.72%)
Mutual labels:  promise
Promise
Promises/A implementation for PHP.
Stars: ✭ 2,078 (+1029.35%)
Mutual labels:  promise

cwait

build status npm monthly downloads npm version

cwait provides a queue handler (TaskQueue) and a wrapper (Task) for promises, to limit how many are being resolved simultaneously. It can wrap any ES6-compatible promises. This allows for example limiting simultaneous downloads with minor changes to existing code. Just wrap your existing "download finished" promise and use it as before.

This is a tiny library with a single dependency, usable both in browsers and Node.js.

Usage

Create a new TaskQueue passing it whatever Promise constructor you're using (ES6, Bluebird, some other shim...) and the maximum number of promise-returning functions to run concurrently. Then just call queue.wrap(<function>) instead of <function> to limit simultaneous execution.

Simple Node.js example:

import * as Promise from 'bluebird';
import {TaskQueue} from 'cwait';

/** Queue allowing 3 concurrent function calls. */
var queue = new TaskQueue(Promise, 3);

Promise.map(list, download); // Download all listed files simultaneously.

Promise.map(list, queue.wrap(download)); // Download 3 files at a time.

See test/test.ts for some runnable code or run it like this:

git clone https://github.com/charto/cwait.git
cd cwait
npm install
npm test

Recursion

Recursive loops that run in parallel require special care. Nested concurrency-limited calls (that are not tail-recursive) must be wrapped in queue.unblock().

Here's a simple example that fails:

var queue = new (require('cwait').TaskQueue)(Promise, 3);

var rec = queue.wrap(function(n) {
    console.log(n);
    return(n && Promise.resolve(rec(n - 1)));
});

rec(10);

It only prints numbers 10, 9 and 8. More calls don't get scheduled because there are already 3 promises pending. For example Node.js exits immediately afterwards because the program is not blocked waiting for any system calls.

Passing a promise to queue.unblock(promise) tells queue that the current function will wait for promise to resolve before continuing. One additional concurrent function is then allowed until the promise resolves.

Be careful not to call queue.unblock() more than once (concurrently) from inside a wrapped function! Otherwise the queue may permit more simultaneous tasks than the intended limit.

Here is a corrected example:

var queue = new (require('cwait').TaskQueue)(Promise, 3);

var rec = queue.wrap(function(n) {
    console.log(n);
    return(n && queue.unblock(Promise.resolve(rec(n - 1))));
});

rec(10);

Advanced example with recursion

The following code recursively calculates the 10th Fibonacci number (55) running 3 recursive steps in parallel, each with an artificial 10-millisecond delay.

At the end, it prints the result (55) and the number of concurrent calls (3).

var queue = new (require('cwait').TaskQueue)(Promise, 3);

var maxRunning = 0;
var running = 0;
var delay = 10;

var fib = queue.wrap(function(n) {
    // "Calculation" begins. Track maximum concurrent executions.
    if(++running > maxRunning) maxRunning = running;

    return(new Promise(function(resolve, reject) {
        setTimeout(function() {
            // "Calculation" ends.
            --running;

            // Each Fibonacci number is the sum of the previous two, except
            // the first ones are 0, 1 (starting from the 0th number).
            // Calculate them in parallel and unblock the queue until ready.

            resolve(n < 2 ? n :
                queue.unblock(Promise.all([
                    fib(n - 1),
                    fib(n - 2)
                ])).then(function(r) {
                    // Sum results from parallel recursion.
                    return(r[0] + r[1]);
                })
            );
        }, delay);
    }));
});

fib(10).then(function(x) {
    console.log('Result: ' + x);
    console.log('Concurrency: ' + maxRunning);
});

API

Docs generated using docts

Class Task

Task wraps a promise, delaying it until some resource gets less busy.
Source code: <>

Methods:

new( ) Task<PromiseType> <>
 ▪ func () => PromiseType
 ▪ Promise PromisyClass<PromiseType>
.delay( ) PromiseType <>
Wrap task result in a new promise so it can be resolved later.
.resume( ) PromiseType <>
Start the task and call onFinish when done.
 ▪ onFinish () => void

Class TaskQueue

Source code: <>

Methods:

new( ) TaskQueue<PromiseType> <>
 ▪ Promise PromisyClass<PromiseType>
 ▪ concurrency number
.add( ) PromiseType <>
Add a new task to the queue.
It will start when the number of other concurrent tasks is low enough.
 ▪ func () => PromiseType
.unblock( ) PromiseType <>
Consider current function idle until promise resolves.
Useful for making recursive calls.
 ▪ promise PromiseType
.wrap( ) (...args: any[]) => PromiseType <>
Wrap a function returning a promise, so that before running
it waits until concurrent invocations are below this queue's limit.
 ▪ func (...args: any[]) => PromiseType
 ▫ thisObject? any

Properties:

.concurrency number
Number of promises allowed to resolve concurrently.

License

The MIT License

Copyright (c) 2015-2017 BusFaster Ltd

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].