All Projects → garronej → run_exclusive

garronej / run_exclusive

Licence: MIT License
⚡🔒 Wait queue for function execution 🔒 ⚡

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to run exclusive

Thunks
A small and magical composer for all JavaScript asynchronous.
Stars: ✭ 523 (+2277.27%)
Mutual labels:  promise, callback, async-await
async
Synchronization and asynchronous computation package for Go
Stars: ✭ 104 (+372.73%)
Mutual labels:  promise, lock, mutex
lightflow
A tiny Promise-inspired control flow library for browser and Node.js.
Stars: ✭ 29 (+31.82%)
Mutual labels:  promise, callback
conquerant
lightweight async/await for Clojure
Stars: ✭ 31 (+40.91%)
Mutual labels:  promise, async-await
of
🍬 Promise wrapper with sugar 🍬
Stars: ✭ 13 (-40.91%)
Mutual labels:  promise, async-await
do
Simplest way to manage asynchronicity
Stars: ✭ 33 (+50%)
Mutual labels:  promise, callback
eslint-config-welly
😎 ⚙️ ESLint configuration for React projects that I do. Feel free to use this!
Stars: ✭ 21 (-4.55%)
Mutual labels:  promise, async-await
ProtoPromise
Robust and efficient library for management of asynchronous operations in C#/.Net.
Stars: ✭ 20 (-9.09%)
Mutual labels:  promise, callback
Escape From Callback Mountain
Example Project & Guide for mastering Promises in Node/JavaScript. Feat. proposed 'Functional River' pattern
Stars: ✭ 249 (+1031.82%)
Mutual labels:  promise, callback
futex
File-based Ruby Mutex
Stars: ✭ 14 (-36.36%)
Mutual labels:  lock, mutex
distlock
The universal component of distributed locks in golang , support redis and postgresql
Stars: ✭ 60 (+172.73%)
Mutual labels:  lock, mutex
debounce-async
A debounce function that delays invoking asynchronous functions.
Stars: ✭ 21 (-4.55%)
Mutual labels:  promise, async-await
mutexsafe
MutexSafe will help you use mutex more effectively. Different mutex for different components are presented. In addition, you can add your own lockers and use within the library.
Stars: ✭ 15 (-31.82%)
Mutual labels:  lock, mutex
mongoose-aggregate-paginate-v2
A cursor based custom aggregate pagination library for Mongoose with customizable labels.
Stars: ✭ 103 (+368.18%)
Mutual labels:  promise, callback
mutex
Mutex lock implementation
Stars: ✭ 28 (+27.27%)
Mutual labels:  lock, mutex
go-lock
go-lock is a lock library implementing read-write mutex and read-write trylock without starvation
Stars: ✭ 78 (+254.55%)
Mutual labels:  lock, mutex
AtomicKit
Concurrency made simple in Swift.
Stars: ✭ 88 (+300%)
Mutual labels:  lock, mutex
Amazon Mws
Amazon MWS NodeJS Wrapper
Stars: ✭ 196 (+790.91%)
Mutual labels:  promise, callback
Await Of
await wrapper for easier errors handling without try-catch
Stars: ✭ 240 (+990.91%)
Mutual labels:  promise, async-await
retryx
Promise-based retry workflow library.
Stars: ✭ 21 (-4.55%)
Mutual labels:  promise, async-await

🔒 Generate functions that do not allow parallel executions 🔒


Let you create functions that enforce no more than one execution happens at the same time.
If the function is called again while there is already an execution ongoing the new call will be queued and executed once all the queued calls have completed.

This is a higher-level approach to the problem addressed by DirtyHairy/async-mutex.

Suitable for any JS runtime env (deno, node, old browser, react-native ...)

  • It is both a Deno and an NPM module.
  • Lightweight, no dependency.
  • No polyfills needed, the NPM module is transpiled down to ES3

Install / Import

Deno

import * as runExclusive from "https://deno.land/x/run_exclusive/mod.ts";

Other javascript runtime environnement:

$ npm install --save run-exclusive
import * as runExclusive from "run-exclusive";

Import from HTML, with CDN

Expose a global (wider browser support):

<script src="//unpkg.com/run-exclusive/bundle.min.js"></script>
<script>
  runExclusive.build(...);
</script>

You can import a specific version unpkg.com

Try it now

Thanks to Stackblitz you can try this lib within your browser like if you where in VSCode.

Screenshot 2020-02-14 at 12 48 04

Run the example

Table of content

Documentation

build()

Let us compare regular functions with run-exclusive functions.

let alphabet= "";

//This function wait a random time then append a letter to alphabet.
async function spell(letter: string): Promise<string>{

    await new Promise(
        resolve=> setTimeout(
            resolve, 
            Math.random()*100
        )
    );

    alphabet+=letter;

    return alphabet;

}

spell("a");
spell("b");
spell("c").then( message => console.log(message)); 
//We cant predict what will be printed to the console,
//it can be "c", "ca", "ac", "cb", "bc", "cab", "cba", "bac", "bca", "acb" or "abc"

Now the same example using run-exclusive:

import * as runExclusive from "run-exclusive";

let alphabet= "";

const spell= runExclusive.build(
    async (letter: string): Promise<string> => {

        await new Promise(
            resolve=>setTimeout(
                resolve, 
                Math.random()*100
            )
        ); 

        alphabet+=letter;

        return alphabet;

    }
);

spell("a");
spell("b");
spell("c").then( message => console.log(message)); // Always prints "abc"

The types definition of the function passed as argument are conserved. Screenshot 2020-02-08 at 15 42 09

createGroupRef()

To share a unique lock among a group of functions.

import * as runExclusive from "run-exclusive";

let alphabet= "";

const groupSpelling= runExclusive.createGroupRef();

const spellUpperCase= runExclusive.build(groupSpelling
    async (letter: string) => {

        await new Promise<void>(resolve=> setTimeout(resolve, Math.random()*100));

        alphabet+=letter.toUpperCase();

    }
);

const spellLowerCase= runExclusive.build(groupSpelling
    async (letter: string) => {

        await new Promise<void>(resolve=> setTimeout(resolve, Math.random()*100));

        alphabet+=letter.toLowerCase();

    }
);

spell("a");
spellUpperCase("b");
spell("c").then(()=> console.log(alphabet)); //prints "aBc".

buildMethod()

If you define run exclusive class methods chances are you want the lock to be restricted to the class's object instance.
This is what buildMethod()is for.

class Student {

    public alphabet= "";

    public spell= runExclusive.buildMethod(
       async (letter: string) => {

            await new Promise<void>(resolve=> setTimeout(resolve, 1000));

            this.alphabet+=letter.toLowerCase();

        }
    );

}

const alice= new Student();
const bob= new Student();

alice.spell("A");
bob.spell("a");
alice.spell("B");
bob.spell("b");
alice.spell("C").then( ()=> console.log(alice.alphabet)); //prints after 3s: "ABC"
bob.spell("c").then( ()=> console.log(bob.alphabet)); //prints after 3s: "abc"

buildCb() and buildMethodCb()

buildCb() is the pending of build() for creating run exclusive functions that complete by invoking a callback. (Instead of resolving a promise).

The only valid reason to use this instead of build() is to be able to retrieve the result synchronously.

WARNING: If you make the callback optional the argument before it cannot be a function.
Be aware that the compiler won't warn you against it.
Example: (getLetter: ()=> string, callback?: (message: string)=> voidA) => {..}
is NOT a valid function to pass to buildCb() or buildMethodCb(). Thanks @AnyhowStep

WARNING: The function should never throw as the exception wont be catchable.

let alphabet= "";

const spell= runExclusive.buildCb(
    (letter: string, callback?: (message: string)=> void) => {

        setTimeout(()=>{

            alphabet+= letter;

            /*
            Callback must always be called, event if the user 
            does not provide one, it is the only way for the module
            to know that the function has completed it's execution.
            You can assume that the callback function is not undefined.
            To tell if the user has provided à callback you can access (callback as any).hasCallback;
            */
            callback!(alphabet);

        }, Math.rand()*100);

    }
};

spell("a");
spell("b");
spell("c", message => console.log(message)); // prints "abc"

NOTE: runExclusive.buildMethodCb() also available.

Queued calls

It is possible to check, for a given run exclusive function, if there is currently an ongoing execution and how many calls are queued. It is also possible to cancel the queued calls.

getQueuedCallCount()

Get the number of queued call of a run-exclusive function. Note that if you call a runExclusive function and call this directly after it will return 0 as there is one function call execution ongoing but 0 queued.

The classInstanceObject parameter is to provide only for the run-exclusive function created with 'buildMethod[Cb].

export declare function getQueuedCallCount(
    runExclusiveFunction: Function, 
    classInstanceObject?: Object
): number;

cancelAllQueuedCalls()

Cancel all queued calls of a run-exclusive function. Note that the current running call will not be cancelled.

The classInstanceObject parameter is to provide only for the run-exclusive function created with 'buildMethod[Cb].

export declare function cancelAllQueuedCalls(
    runExclusiveFunction: Function, 
    classInstanceObject?: Object
): number;

isRunning()

Tell if a run-exclusive function has an instance of it's call currently being performed.

The classInstanceObject parameter is to provide only for the run-exclusive function created with 'buildMethod[Cb].

export declare function isRunning(
    runExclusiveFunction: Function, 
    classInstanceObject?: Object
): boolean;

getPrComplete()

Return a promise that resolve when all the current queued call of a runExclusive functions have completed.
The classInstanceObject parameter is to provide only for the run-exclusive function created with 'buildMethod[Cb].

export declare function getPrComplete(
    runExclusiveFunction: Function, 
    classInstanceObject?: Object
): Promise<void>;
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].