{"id":15386999,"url":"https://github.com/gkjohnson/threading-js","last_synced_at":"2025-11-13T22:54:14.845Z","repository":{"id":46941281,"uuid":"108351173","full_name":"gkjohnson/threading-js","owner":"gkjohnson","description":"Wrapper for Web Workers for easily running a function from the client without serving the worker a script","archived":false,"fork":false,"pushed_at":"2023-10-26T22:56:10.000Z","size":1919,"stargazers_count":18,"open_issues_count":13,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-15T19:53:37.213Z","etag":null,"topics":["browser","javascript","performance","process","subprocess","thread","threads","transfer","webworker","webworkers","workers"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gkjohnson.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-10-26T02:25:48.000Z","updated_at":"2025-01-31T20:57:27.000Z","dependencies_parsed_at":"2024-10-18T18:59:22.331Z","dependency_job_id":"2b1ec13c-f633-4c72-a682-3d50fe2520e3","html_url":"https://github.com/gkjohnson/threading-js","commit_stats":{"total_commits":136,"total_committers":2,"mean_commits":68.0,"dds":"0.16911764705882348","last_synced_commit":"d56c091f0a64073a0a94562a9a317c4e29e37839"},"previous_names":["gkjohnson/javascript-thread-runner"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/gkjohnson/threading-js","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Fthreading-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Fthreading-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Fthreading-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Fthreading-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gkjohnson","download_url":"https://codeload.github.com/gkjohnson/threading-js/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gkjohnson%2Fthreading-js/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284304462,"owners_count":26982161,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-13T02:00:06.582Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","javascript","performance","process","subprocess","thread","threads","transfer","webworker","webworkers","workers"],"created_at":"2024-10-01T14:51:08.968Z","updated_at":"2025-11-13T22:54:14.804Z","avatar_url":"https://github.com/gkjohnson.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# threading-js\n\n[![npm version](https://img.shields.io/npm/v/threading-js.svg?style=flat-square)](https://www.npmjs.com/package/threading-js)\n[![travis build](https://img.shields.io/travis/gkjohnson/threading-js.svg?style=flat-square)](https://travis-ci.org/gkjohnson/threading-js)\n[![lgtm code quality](https://img.shields.io/lgtm/grade/javascript/g/gkjohnson/threading-js.svg?style=flat-square\u0026label=code-quality)](https://lgtm.com/projects/g/gkjohnson/threading-js/)\n\nSmall wrapper for browser [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) that simplfies running tasks and allows running without having to serve a worker script to the client.\n\n## Use\nSimple example showing how to use a Thread to interleave two arrays together using a SharedArrayBuffer. Using basic arrays increases the run time due to copying the data. ArrayBuffer ownership can be transferred using the `transferList` parameter in `run` and `postMessage`.\n\nThe function being passed to the thread must be completely self-contained and only reference data in the passed 'context' object or loaded scripts. All data passed into the context object will be stringified to be copied.\n\n#### With ES6 Imports\n\nExample [here](./example/index.html)\n\n```js\nimport Thread from '.../node_modules/threading-js/Thread.js'\n\n// Operation functions\nconst interleave = (a, b, res) =\u003e {\n  let i = 0\n  while(true) {\n    if (i \u003e= a.length || i \u003e= b.length) break\n\n    res[2 * i + 0] = a[i]\n    res[2 * i + 1] = b[i]\n    i++\n  }\n  return res\n}\n\nconst threadFunc = args =\u003e {\n  const arr1 = args.arr1\n  const arr2 = args.arr2\n  const res = args.res\n\n  postMessage('starting')\n  const data = interleave(arr1, arr2, res)\n  postMessage('done')\n\n  return data\n}\n\n// Create thread\nconst thread = new Thread(threadFunc, { interleave })\n\n// Create data\nconst ARRAY_LENGTH = 10000000\nconst arr1 = new Float32Array(new SharedArrayBuffer(ARRAY_LENGTH * 4))\nconst arr2 = new Float32Array(new SharedArrayBuffer(ARRAY_LENGTH * 4))\nconst sharedres = new Float32Array(new SharedArrayBuffer(ARRAY_LENGTH * 4 * 2))\nfor(let i = 0; i \u003c ARRAY_LENGTH; i++) {\n  arr1[i] = Math.random()\n  arr2[i] = Math.random()\n}\n\n// Run the tests\nconsole.time('main thread run')\ninterleave(arr1, arr2, sharedres)\nconsole.timeEnd('main thread run')\n\nconsole.time('initial thread run')\nthread\n    .run({ arr1, arr2, res: sharedres }, log =\u003e console.log(log))\n    .then(res =\u003e {\n        console.timeEnd('initial thread run')\n\n        console.time('subsequent thread run')\n        return thread.run({ arr1, arr2, res: sharedres }, log =\u003e console.log(log))\n    })\n    .then(res =\u003e {\n        console.timeEnd('subsequent thread run')\n    })\n\n// main thread run: 30.962158203125ms\n// starting\n// done\n// initial thread run: 111.95703125ms\n// starting\n// done\n// subsequent thread run: 35.179931640625ms\n```\n\n#### With UMD\n\nExample [here](./example/index.umd.html)\n\n```html\n\u003cscript type=\"text/javascript\" src=\"../umd/Thread.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\" src=\"../umd/ThreadPool.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\" src=\"../umd/ThreadQueue.js\"\u003e\u003c/script\u003e\n\n\u003cscript\u003e\n  const Thread = window.Thread.default\n  const thread = new Thread(...)\n\n  // ...use the thread...\n\u003c/script\u003e\n```\n\n#### Getting the Best Performance\n\n##### Data Clone Pitfalls\n\nWhen basic Javascript objects are transferred between the UI thread and a Web Worker (via `run()` in this library), they are copied using the [Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm), which introduces a significant overhead that can be so bad that it completely defeats the purpose of using a thread. Using shared or transferred buffers is preferable.\n\n##### Transferable Objects and ArrayBuffers\n\nSome objects can have their [ownership transferred between the threads](https://developer.mozilla.org/en-US/docs/Web/API/Transferable), removing the need for cloning the data and associated overhead. A buffer is transferred using the `run()` function in this library and passing the object into the `transferList` array. Once an object has been transferred it's no longer accessible from the original thread and must be explicitly transferred back using a call to `postMessage()`. If an item is not in the transferList, then it is copied.\n\n##### SharedArrayBuffers\n\n[SharedArrayBuffers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) are not copied, but don't need to be in the `transferList`, either. These buffers can be read from multiple threads at once making them an ideal vessel for data processing and return objects. Synchronized writes, however, must be accounted for.\n\n# API\n\n## Thread\n\n### constructor(threadFunc, context, srcs)\nThe constructor takes a function to run, a dictionary of context data and functions for use in the thread function, and an array of remote source URLs to load libraries in from.\n\n`threadFunc` is the function to run in the worker. The value returned by this function will be passed back as the result of the run. `postMessage` can be used in this, as well, to post intermediate results back to the main thread.\n\n`context` is a shallow dictionary of data or functions to be injected into the web worker scope.\n\n`srcs` is an array of script URLs to load from.\n\n### running\nWhether or not the thread is running\n\n### ready\nWhether or not the thread is ready\n\n### run(args, intermediateFunc, transferList)\nRuns the thread function with the args value as an argument to the function.\n\n`intermediateFunc` is a callback to recieve intermediate postMessage results from the function. Use the intermediate postMessage function to transfer items as there's no way to return a list of items to transfer from thread function.\n\n`transferList` the equivelant of the `postMessage` transfer list argument. Note that items in the transfer list are automatically retured once the run is completed.\n\nReturns a promise.\n\n### cancel()\nCancels the current run and prepares for a new one.\n\n### dipose()\nDisposes of the Thread data so it can't be used anymore.\n\n## ThreadPool\nA thread pool for easily running many of the same type of task in parallel.\n\n### constructor(capacity, func, context, srcs, options)\nLike the thread constructor, but takes a capacity as the first argument.\n\n**options.initializeImmediately = true**: Creates all the threads immediately instead of lazily creating them so no intialization overhead is incurred.\n\n### ready\nWhether the pool has inactive threads.\n\n### activeThreads\nThe number of currently inactive threads.\n\n### capacity\nThe total possible number of threads the pool can support.\n\n### run(...)\nGet and use an available thread to run the requested task. Behaves like `Thread.run`, but returns `null` if there are not threads available in the pool.\n\n### dispose()\nDispose of all threads and data.\n\n## ThreadQueue\nA helper class for creating a job queue and running through the tasks using as many threads to work as the capacity allows.\n\n### constructor(...)\nSame as the `ThreadPool` constructor.\n\n### run(...)\nSame as `Thread.run`.\n\n### dispose()\nSame as `ThreadPool.dispose`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgkjohnson%2Fthreading-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgkjohnson%2Fthreading-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgkjohnson%2Fthreading-js/lists"}