All Projects → dmotz → commune.js

dmotz / commune.js

Licence: MIT license
Web workers lose their chains: Easy threads without separate function files.

Programming Languages

coffeescript
4710 projects

Projects that are alternatives of or similar to commune.js

react-use-comlink
Three ways to use Comlink web workers through React Hooks (and in a typesafe manner).
Stars: ✭ 39 (+129.41%)
Mutual labels:  web-workers
holdem
A texas holdem simulator build with WebAssembly and web workers
Stars: ✭ 42 (+147.06%)
Mutual labels:  web-workers
Zip.js
JavaScript library to zip and unzip files in the browser and Deno
Stars: ✭ 2,444 (+14276.47%)
Mutual labels:  web-workers
Useworker
⚛️ useWorker() - A React Hook for Blocking-Free Background Tasks
Stars: ✭ 2,233 (+13035.29%)
Mutual labels:  web-workers
Workly
A really simple way to move a function or class to a web worker. 🏋️‍♀️→ 😄
Stars: ✭ 1,848 (+10770.59%)
Mutual labels:  web-workers
Workerize
🏗️ Run a module in a Web Worker.
Stars: ✭ 4,134 (+24217.65%)
Mutual labels:  web-workers
taggr
⚡️ Rediscover your memories while keeping your privacy.
Stars: ✭ 20 (+17.65%)
Mutual labels:  web-workers

Karl

Commune.js

Web workers lose their chains

Dan Motzenbecker, MIT License

Intro

Commune.js makes it easy to run computationally heavy functions in a separate thread and retrieve the results asynchronously. By delegating these functions to a separate thread, you can avoid slowing down the main thread that affects the UI. Think of it as a way to leverage the web workers API without ever having to think about the web workers API.

Using straightforward syntax, you can add web worker support to your app's functions without the need to create separate files (as web workers typically require) and without the need to change the syntax of your functions. Best of all, everything will work without problems on browsers that do not support web workers.

Usage

Here's an example where the first argument is the function to thread, the second argument is an array of arguments to pass to it, and the third is a callback to handle the result once it comes through:

var heavyFunction = function(a, b, c){
    // do some work 100 million times
    for(var i = 0; i < 1e9; i++){
        a++;
        b++;
        c++;
    }
    // return arguments modified
    return [a, b, c];
}

commune(heavyFunction, [1, 2, 3], function(result){
    console.log(result); // [100000001, 100000002, 100000003]
});

//go ahead and continue with more work in the main thread without being held up:
console.log('I will appear before the loop finishes.');

setTimeout(function(){
    console.log('I probably will too, depending on how fast your CPU is.');
}, 500);

In a browser that supports worker threads, the above will output:

I will appear before the loop finishes.
I probably will too, depending on how fast your CPU is.
[100000001, 100000002, 100000003]

In a browser without web worker support, everything still works, just in a different order:

[100000001, 100000002, 100000003]
I will appear before the loop finishes.
I probably will too, depending on how fast your CPU is.

With Commune.js, we could proceed with our work in the main thread without waiting to loop 100 million times.

Further proof:

commune(heavyFunction, [1, 2, 3], function(result){
    console.log(result); // [100000001, 100000002, 100000003]
});

commune(heavyFunction, [50, 60, 70], function(result){
    console.log(result); // [100000050, 100000060, 100000070]
});

commune(heavyFunction, [170, 180, 190], function(result){
    console.log(result); // [100000170, 100000180, 100000190]
});

Running the above in a browser with worker support, you'll see the results of each function call appear simultaneously, meaning that none of these large loops had to wait for the others to finish before starting. Using Commune.js with care, you can bring asynchronicity and parallelism to previously inapplicable areas.

To simplify things more, you can DRY up your syntax with the help of communify() which transforms your vanilla function into a Commune-wrapped version:

var abcs = function(n){
    var s = '';
    for(var i = 0; i < n; i++){
        s += 'abc';
    }
    return s;
}

// Communify the function for future calls:
abcs = communify(abcs);

// Or designate some partial application:
abcs = communify(abcs, [5]);

// Then call it later in a simplified manner:
abcs(function(s){
    console.log('my opus:', s);
});

// Even cleaner with named functions:
abcs(alert);

// If you didn't use partial application with the original communify call:
abcs([10], alert);

How It Works

When you pass a new function to Commune.js, it creates a modified version of the function using web worker syntax. Commune.js memoizes the result so additional calls using the same function don't have to be rewritten.

Just write your functions as you normally would using return statements.

Commune.js automatically creates binary blobs from your functions that can be used as worker scripts.

Caveats

Since web workers operate in a different context, you can't reference any variables outside of the function's scope (including the DOM) and you can't use references to this since it will refer to the worker itself. For functions you want to use Commune.js with, use a functional style where they return a modified version of their input.

Also, since this is an abstraction designed for ease-of-use and flexibility, it does not work exactly as web workers do -- namely you can't have multiple return events from a single worker.

Commune.js is an early stage experiment so contributions and ideas are very welcome.

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].