# Multithreading | Functional JavaScript To Speedup Heavy Workloads

**URL:** <https://onehack.st/t/multithreading-functional-javascript-to-speedup-heavy-workloads/289125>\
**Category:** Tools & Scripts\
**Tags:** programming\
**Created:** [August 16, 2024, 7:23pm UTC](https://onehack.st/t/multithreading-functional-javascript-to-speedup-heavy-workloads/289125 "2024-08-16T19:23:46Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Prometheus](https://onehack.st/user_avatar/onehack.st/prometheus/32/34950_2.png) [@Prometheus](https://onehack.st/u/Prometheus)\
**Post date:** [August 16, 2024, 7:23pm UTC](https://onehack.st/t/multithreading-functional-javascript-to-speedup-heavy-workloads/289125/1 "2024-08-16T19:23:47Z")

</div>

[![Multithreading Banner](https://private-user-images.githubusercontent.com/38042257/294755580-ead29359-37c3-4fd2-819b-349ddeec5524.svg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjM4MzYyODgsIm5iZiI6MTcyMzgzNTk4OCwicGF0aCI6Ii8zODA0MjI1Ny8yOTQ3NTU1ODAtZWFkMjkzNTktMzdjMy00ZmQyLTgxOWItMzQ5ZGRlZWM1NTI0LnN2Zz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE2VDE5MTk0OFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTMzMmNhNDhjYjYyZDMwZTg4ZThjM2FiZmIzNDhhNjM4YWRiNTJmNjg5NmFkZDg0YWVmNDY1OTNjZjk3MDc3MDImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.Cl7F4LJd2OiTtsbB4aBh0gI-W9muoI7qwD2Lqhpvwyo)](https://multithreading.io/)

[![License](https://camo.githubusercontent.com/6b4c46847f0256b0a6a3c0219d0bd37095245b5b6d9f7deff8d7d7684523e5ae/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f573447312f6d756c7469746872656164696e67)](https://github.com/W4G1/multithreading/blob/main/LICENSE.md) [![Downloads](https://camo.githubusercontent.com/91f388d61184beb7e1fc831cce4c7d724c13e87ca0397118cb884b77ee6b5909/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64772f6d756c7469746872656164696e673f636f6c6f723d253233383935364646)](https://www.npmjs.com/package/multithreading) [![NPM version](https://camo.githubusercontent.com/85ab51bcb94d22f1cc15f9520195450499e8873349dc54d1cc219c0ba7887164/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f6d756c7469746872656164696e67)](https://www.npmjs.com/package/multithreading?activeTab=versions) [![GitHub Repo stars](https://camo.githubusercontent.com/28ec20f40eb32e1a3a5b7b3cb99670de8d52d788e2974d8d5587649130afdac8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f573447312f6d756c7469746872656164696e673f6c6f676f3d676974687562266c6162656c3d53746172266c6162656c436f6c6f723d726762283236253243253230333025324325323033352926636f6c6f723d7267622831332532432532303137253243253230323329)](https://github.com/W4G1/multithreading) [![Node.js CI](https://github.com/W4G1/multithreading/actions/workflows/node.js.yml/badge.svg)](https://github.com/W4G1/multithreading/actions/workflows/node.js.yml)

# multithreading

Multithreading is a tiny runtime that allows you to execute JavaScript functions on separate threads. It is designed to be as simple and fast as possible, and to be used in a similar way to regular functions.

With a minified size of only 4.5kb, it has first class support for [Node.js](https://nodejs.org/), [Deno](https://deno.com/) and the [browser](https://caniuse.com/?search=webworkers). It can also be used with any framework or library such as [React](https://react.dev/), [Vue](https://vuejs.org/) or [Svelte](https://svelte.dev/).

Depending on the environment, it uses [Worker Threads](https://nodejs.org/api/worker_threads.html) or [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Worker). In addition to [ES6 generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) to make multithreading as simple as possible.

### The State of Multithreading in JavaScript

JavaScript’s single-threaded nature means that tasks are executed one after the other, leading to potential performance bottlenecks and underutilized CPU resources. While [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Worker) and [Worker Threads](https://nodejs.org/api/worker_threads.html) offer a way to offload tasks to separate threads, managing the state and communication between these threads is often complex and error-prone.

This project aims to solve these challenges by providing an intuitive Web Worker abstraction that mirrors the behavior of regular JavaScript functions. This way it feels like you’re executing a regular function, but in reality, it’s running in parallel on a separate threads.

## Installation

npm install multithreading

## Usage

#### Basic example

import { threaded } from “multithreading”; const add = threaded(function\* (a, b) { return a + b; }); console.log(await add(5, 10)); // 15

The `add` function is executed on a separate thread, and the result is returned to the main thread when the function is done executing. Consecutive invocations will be automatically executed in parallel on separate threads.

#### Example with shared state

import { threaded, $claim, $unclaim } from “multithreading”; const user = { name: “john”, balance: 0, }; const add = threaded(async function\* (amount) { yield user; // Add user to dependencies await $claim(user); // Wait for write lock user.balance += amount; $unclaim(user); // Release write lock }); await Promise.all([add(5), add(10),]); console.log(user.balance); // 15

This example shows how to use a shared state across multiple threads. It introduces the concepts of claiming and unclaiming write access using `$claim` and `$unclaim`. This is to ensure that only one thread can write to a shared state at a time.

> Always `$unclaim()` a shared state after use, otherwise the write lock will never be released and other threads that want to write to this state will be blocked indefinitely.

The `yield` statement is used to specify external dependencies, and must be defined at the top of the function.

#### Example with external functions

import { threaded, $claim, $unclaim } from “multithreading”; // Some external function function add (a, b) { return a + b; } const user = { name: “john”, balance: 0, }; const addBalance = threaded(async function\* (amount) { yield user; yield add; // Add external function to dependencies await $claim(user); user.balance = add(user.balance, amount); $unclaim(user); }); await Promise.all([addBalance(5), addBalance(10),]); console.log(user.balance); // 15

In this example, the `add` function is used within the multithreaded `addBalance` function. The `yield` statement is used to declare external dependencies. You can think of it as a way to import external data, functions or even packages.

As with previous examples, the shared state is managed using `$claim` and `$unclaim` to guarantee proper synchronization and prevent data conflicts.

> External functions like `add` cannot have external dependencies themselves. All variables and functions used by an external function must be declared within the function itself.

### Using imports from external packages

When using external modules, you can dynamically import them by using `yield "some-package"`. This is useful when you want to use other packages within a threaded function.

import { threaded } from “multithreading”; const getId = threaded(function\* () { /\*\* \* @type {import(“uuid”)} \*/ const { v4 } = yield “uuid”; // Import other package return v4(); } console.log(await getId()); // 1a107623-3052-4f61-aca9-9d9388fb2d81

You can also import external modules in a variety of other ways:

const { v4 } = yield “npm:uuid”; // Using npm specifier (available in Deno) const { v4 } = yield “[https://esm.sh/uuid](https://esm.sh/uuid)”; // From CDN url (available in browser and Deno)

## Enhanced Error Handling

Errors inside threads are automatically injected with a pretty stack trace. This makes it easier to identify which line of your function caused the error, and in which thread the error occured.

[![Example of an enhanced stack trace](https://private-user-images.githubusercontent.com/38042257/294755558-4c5b3352-ad19-4270-86e4-dad6fc6e0fe6.svg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjM4MzYyODgsIm5iZiI6MTcyMzgzNTk4OCwicGF0aCI6Ii8zODA0MjI1Ny8yOTQ3NTU1NTgtNGM1YjMzNTItYWQxOS00MjcwLTg2ZTQtZGFkNmZjNmUwZmU2LnN2Zz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE2VDE5MTk0OFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTAyNTBiZWNhNjM2MTc1OTg0N2MxYWU3N2QyZWVjZmRjNWRjZjNmYWEzNDg1Y2Q1MGQyZDMxNmJjZGU2ZGI3NmYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.tBayPtO8-Wu3H5I9zg7sqLngMkvnI5Mw72cyZTlBzBo)](https://private-user-images.githubusercontent.com/38042257/294755558-4c5b3352-ad19-4270-86e4-dad6fc6e0fe6.svg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjM4MzYyODgsIm5iZiI6MTcyMzgzNTk4OCwicGF0aCI6Ii8zODA0MjI1Ny8yOTQ3NTU1NTgtNGM1YjMzNTItYWQxOS00MjcwLTg2ZTQtZGFkNmZjNmUwZmU2LnN2Zz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE2VDE5MTk0OFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTAyNTBiZWNhNjM2MTc1OTg0N2MxYWU3N2QyZWVjZmRjNWRjZjNmYWEzNDg1Y2Q1MGQyZDMxNmJjZGU2ZGI3NmYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.tBayPtO8-Wu3H5I9zg7sqLngMkvnI5Mw72cyZTlBzBo)

## GitHub:

[https://github.com/W4G1/multithreading](https://github.com/W4G1/multithreading)
