{"id":32597905,"url":"https://github.com/nytamin/threadedclass","last_synced_at":"2025-10-30T05:19:54.041Z","repository":{"id":32383208,"uuid":"132416314","full_name":"nytamin/threadedClass","owner":"nytamin","description":"Fork instances of classes with one line of code, all while retaining the types of the class.","archived":false,"fork":false,"pushed_at":"2025-10-20T18:29:42.000Z","size":6736,"stargazers_count":5,"open_issues_count":8,"forks_count":7,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-10-20T20:37:44.122Z","etag":null,"topics":["asynchronous","hacktoberfest","multi-threading","multithreading","sofie","thread"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/nytamin.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-05-07T06:23:21.000Z","updated_at":"2025-10-20T18:29:40.000Z","dependencies_parsed_at":"2024-04-23T01:30:15.217Z","dependency_job_id":"93a78d28-da78-4df1-b6ea-7b7b0bfbc5cf","html_url":"https://github.com/nytamin/threadedClass","commit_stats":{"total_commits":344,"total_committers":10,"mean_commits":34.4,"dds":"0.33720930232558144","last_synced_commit":"aa1309b1eeebc86108940454673103a576a24788"},"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"purl":"pkg:github/nytamin/threadedClass","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nytamin%2FthreadedClass","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nytamin%2FthreadedClass/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nytamin%2FthreadedClass/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nytamin%2FthreadedClass/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nytamin","download_url":"https://codeload.github.com/nytamin/threadedClass/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nytamin%2FthreadedClass/sbom","scorecard":{"id":700010,"data":{"date":"2025-08-11","repo":{"name":"github.com/nytamin/threadedClass","commit":"536fd20442286a8e2da1300180de8778f6084f84"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4,"checks":[{"name":"Maintained","score":8,"reason":"10 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 8","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":4,"reason":"Found 2/5 approved changesets -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/lint-and-test.yml:1","Warn: no topLevel permission defined: .github/workflows/publish-docs.yml:1","Warn: no topLevel permission defined: .github/workflows/publish-nightly.yml:1","Warn: no topLevel permission defined: .github/workflows/publish-release.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint-and-test.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/lint-and-test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint-and-test.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/lint-and-test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint-and-test.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/lint-and-test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint-and-test.yml:54: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/lint-and-test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint-and-test.yml:56: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/lint-and-test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint-and-test.yml:60: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/lint-and-test.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/lint-and-test.yml:77: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/lint-and-test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-docs.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-docs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-docs.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-docs.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish-docs.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-docs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-nightly.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-nightly.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-nightly.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-nightly.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-release.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-release.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-release.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-release.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-release.yml:52: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-release.yml:56: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-release.yml:87: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-release.yml:89: update your workflow using https://app.stepsecurity.io/secureworkflow/nytamin/threadedClass/publish-release.yml/master?enable=pin","Info:   0 out of  18 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 27 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"13 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-mhxj-85r3-2x55","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-4wf5-vphf-c2xc","Warn: Project is vulnerable to: GHSA-7p7h-4mm5-852v","Warn: Project is vulnerable to: GHSA-776f-qx25-q3cc","Warn: Project is vulnerable to: GHSA-p9pc-299p-vxgp"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T04:58:48.695Z","repository_id":32383208,"created_at":"2025-08-22T04:58:48.695Z","updated_at":"2025-08-22T04:58:48.695Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281748754,"owners_count":26554835,"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-10-30T02:00:06.501Z","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":["asynchronous","hacktoberfest","multi-threading","multithreading","sofie","thread"],"created_at":"2025-10-30T05:19:46.061Z","updated_at":"2025-10-30T05:19:54.035Z","avatar_url":"https://github.com/nytamin.png","language":"TypeScript","readme":"# Threaded class\n[![Lint and Test](https://github.com/nytamin/threadedClass/actions/workflows/lint-and-test.yml/badge.svg)](https://github.com/nytamin/threadedClass/actions/workflows/lint-and-test.yml)\n[![codecov](https://codecov.io/gh/nytamin/threadedClass/branch/master/graph/badge.svg)](https://codecov.io/gh/nytamin/threadedClass)\n\nFork instances of classes (while keeping typings) with one line of code.\n\n## Getting started\n\n```\nnpm install threadedclass\n```\nLet's say you have a class that has several computational-heavy methods:\n```typescript\n// Normal, single-threaded way:\nimport { Professor } from './professor'\n\nfunction getStory() {\n  let mrSmith = new Professor('maths', 'greek')\n  let story = mrSmith.talkAboutAncientGreece() // takes a loong time\n  return story\n}\n```\n`Threaded-class` helps you create an asynchronous version of the instance of that class.\nThe instance will have _almost_ the same typings-API as the original (all methods return promises instead), but will run in a separate thread.\n```typescript\n// Multi-threaded, asynchronous way:\nimport { threadedClass} from 'threadedclass'\nimport { Professor } from './professor'\n\nasync function getStory() {\n  let mrSmith = await threadedClass\u003cProfessor\u003e('./professor.js', 'Professor', ['maths', 'greek'])\n  let story = await mrSmith.talkAboutAncientGreece() // still takes a loong time, but now runs in a separate thread\n  return story\n}\n```\nThe instance returned by `threadedClass()` has methods equivalent to the original, but all properties and methods will be asynchronous (return Promises).\n\n## API\n[API reference](https://nytamin.github.io/threadedClass)\n### NodeJS: Typescript example\n```typescript\nimport { threadedClass} from  'threadedclass'\nimport { Professor } from './professor'\n\nconst mrSmith = await threadedClass\u003cProfessor\u003e(\n   './professor.js',     // Path to imported module (this should be the same path as is in require('XX') or import {class} from 'XX'} )\n   'Professor' ,        // The export name for the class to be forked\n   ['maths', 'greek'], // Array of arguments to be fed into the class constructor\n   {} // Config (see below)\n)\nconst story = await mrSmith.talkAboutAncientGreece() // All methods returns a Promise now\nconsole.log(story)\n\n```\n### NodeJS: Javascript example\n```javascript\nvar threadedClass = require('threadedclass').threadedClass\nvar Professor = require('./professor')\n\nconst mrSmith = await threadedClass('./professor.js', Professor, ['maths', 'greek'])\n\nconst story = await mrSmith.talkAboutAncientGreece() // All methods returns a Promise now\nconsole.log(story)\n\n```\n### Browser: Javascript example\n[Example](https://nytamin.github.io/threadedClass/examples/browser.html)\n```html\n\u003cscript type=\"text/javascript\" src=\"lib/threadedClass.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\" src=\"professor.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\"\u003e\n   var threadedClass = ThreadedClass.threadedClass\n\n   threadedClass('../professor.js', Professor, ['maths', 'greek'], { // path to module is relative to threadedClass.js\n      pathToWorker: 'lib/threadedclass-worker.js' // in browser, a path to the worker-scrip must also be provided\n   })\n   .then(async (mrSmith) =\u003e {\n      const story = await mrSmith.talkAboutAncientGreece() // All methods returns a Promise now\n      console.log(story)\n   })\n\u003c/script\u003e\n```\n### Options\nAn optional options object can be passed to threadedClass() with the following properties:\n\n| Option | Type | Description |\n|--|--|--|\n| `threadUsage` | number | A number between 0 - 1, how large part of a thread the instance takes up. For example; if set to 0.1, a thread will be re-used for up to 10 instances. |\n| `threadId` | string | Set to an arbitrary id to put the instance in a specific thread. Instances with the same threadIds will be put in the same thread. |\n| `autoRestart` | boolean | If the process crashes or freezes it's automatically restarted. (ThreadedClassManager will emit the \"restarted\" event upon restart) |\n| `restartTimeout` | number | (milliseconds), if the process needs to restart, how long to wait for it to initalize, before failing. (default is 1000ms, 0 disables this timeout) |\n| `autoRestartRetryCount` | number | If an autoRestart fails and this is set, ThreadedClass will continue to try to restart the thread. (defaults is 1, 0 means continue to restart indefinitely) |\n| `autoRestartRetryDelay` | number | (milliseconds), how long to wait before retrying to restart the thread after autoRestart fails. (default is 1000 ms) |\n| `killTimeout` | number | (milliseconds), if the process is being killed, how long to wait for it to terminate, before failing. (default is 1000ms, 0 disables this timeout)  |\n| `disableMultithreading` | boolean | Set to true to disable multi-threading, this might be useful when you want to disable multi-threading but keep the interface unchanged. |\n| `pathToWorker` | string | Set path to worker, used in browser |\n| `freezeLimit` | number | (milliseconds), how long to wait before considering the child to be unresponsive. (default is 1000 ms, 0 disables this timeout) |\n| `instanceName` | string | Optional: Set a custom name of the instance (used for debugging). Defaults to the class name |\n\n### ThreadedClassManager API\n\n```typescript\nimport { ThreadedClassManager } from 'threadedclass'\n\n // Debug mode, will log stuff to console\nThreadedClassManager.debug = true\n\n// Enable strict mode.\n// When strict mode is enabled, checks will be done to ensure that best-practices are followed (such as listening to the proper events, etc).\n// Warnings will be output to the console if strict mode is enabled.\nThreadedClassManager.strict = true\n\n// Whether ThreadedClass will register exit handlers. If not, then the application should ensure the threads are aborted on process exit\nThreadedClassManager.handleExit = RegisterExitHandlers.AUTO // Default, checks if exit handlers have been set up by user before first threadedClass() call.\nThreadedClassManager.handleExit = RegisterExitHandlers.YES // Will set up exit handlers to ensure child processes are killed on exit signal.\nThreadedClassManager.handleExit = RegisterExitHandlers.NO // Don't set up any exit handlers (depending on your environment and Node version, children might need to be manually killed).\n\n// Destroy a proxy instance\nawait ThreadedClassManager.destroy(mrSmith)\n\n// Destroys all proxy instances and closes all threads\nawait ThreadedClassManager.destroyAll()\n\n// Returns the number of threads / child processes\nThreadedClassManager.getThreadCount()\n\n// Returns memory usage for each thread\nconst memUsage = await ThreadedClassManager.getThreadsMemoryUsage()\n\n// Set up an event listener for an instance\nThreadedClassManager.onEvent(mrSmith, 'thread_closed', () =\u003e {}) // This event is fired if a thread has closed. If autoRestart is set, an attempt to auto-restart the thread will be made after this\nThreadedClassManager.onEvent(mrSmith, 'restarted', () =\u003e {}) // This event is fired after an instance has been successfully restarted\nThreadedClassManager.onEvent(mrSmith, 'error', (error) =\u003e {}) // This event is fired if there is an unhandled error in the thread\n\n// Restart the thread of the proxy instance, useful if you don't use autoRestart and want to handle restarts manually.\nawait ThreadedClassManager.restart(mrSmith)\n\n// Returns how the threads are implemented ( not_supported, web_worker, worker_threads, child_process )\nconst mode = ThreadedClassManager.getThreadMode()\n\n```\n\n### Recommended usage\n\nTo avoid bugs and unexpected behaviours, it is recommended that you follow the pattern below:\n\n```typescript\nimport { threadedClass} from  'threadedclass'\nimport { Professor } from './professor'\n\n\nThreadedClassManager.strict = true // This activates a few checks that the events are listened to, etc..\n\nconst mrSmith = await threadedClass\u003cProfessor\u003e('./professor.js', 'Professor', ['maths', 'greek'], {\n   threadUsage: 1, // Optional, set this to 1 if there should only be 1 instance per thread (and 0.1 will allow up to 10 instances per thread)\n   autoRestart: true, // Set this to true to auto-restart the class upon a process crash. You'll be notified with the \"restarted\" event after an auto-restart.\n})\nawait mrSmith.loadInitialData() // An example of an asyncronous initializing procedure\n\nThreadedClassManager.onEvent(mrSmith, 'thread_closed', () =\u003e {\n   // This event is fired if a thread has closed.\n   // If autoRestart is set, an attempt to auto-restart the thread will be made after this\n})\nThreadedClassManager.onEvent(mrSmith, 'restarted', () =\u003e {\n   // This event is fired after an instance has been successfully restarted\n\n   // If applicable, you might want to re-initialize the instance at this point:\n   await mrSmith.loadInitialData()\n})\nThreadedClassManager.onEvent(mrSmith, 'error', (error) =\u003e {\n   // This event is fired if there is an unhandled error in the thread\n   console.error(error)\n})\n\nawait mrSmith.talkAboutAncientGreece() // All methods returns a Promise\n\n\nfunction onShutdown() {\n   // If ThreadedClassManager.handleExit is set to RegisterExitHandlers.NO\n   // You should call this when shutting down, to ensure that any child processes are closed properly:\n   await ThreadedClassManager.destroyAll()\n}\n\n```\n\n## Features\n\n### Supported imports\n* Classes imported from _your own modules_. `import { MyClass } from './myModule'`\n* Classes imported from _external dependencies_. `import { DatClass } from 'dat-library'`\n* Classes importted from _native Node modules_. `import { StringDecoder } from 'string_decoder'`\n\n### Supported methods, arguments / parameters \u0026 return values\nWhen calling a method of your threaded instance (`threaded.myMethod()`), there are some limitations to what data-types are allowed to be provided and returned.\n\n#### Supported data types\n* All JSON-serializable types; numbers, strings, arrays, objects etc..\n* Buffers\n* Functions (such as callbacks or returned functions)\n\n#### Unsupported data types\n* Non-JSON-encodable types, such as objects with *cyclic references* (except when in worker_threads, then it's fine).\n* Instances of classes (the instance will be serialized as JSON and piped through, but its methods will not).\n\n## Known limitations\n* The to-be-threaded class must not be referencing any global variables, as the class is run in its own sandbox.\n* **No garbage-collection of callback-functions**\n    Currently, if you give a callback to a method (like so: `threaded.myMethod(() =\u003e {})`) a reference to the method will be stored indefinitely, because we cannot determine if the reference is valid in the child process.\n* There is a noticable delay when spawning a new thread, and since each thread is its own Node-process it uses up a few Megabytes of memory. If you intend to spawn many instances of a class, consider using the _threadUsage_ option (for example `threadUsage: 0.1` will put 10 instances in a thread before spawning a new).\n\n## Under the hood\n### Used API:s\nDifferent API:s will be used for threading, depending on the platform:\n\n| Platform | API used   |\n| --- | -- |\n| [Browser](https://caniuse.com/#feat=webworkers) | Web-workers |\n| NodeJS \u003c10.x | Child process |\n| NodeJS 10.x - 11.7 | Worker-threads (if `node --experimental-worker` flag is enabled) |\n| NodeJS \u003e11.8 | Worker-threads |\n\n### Notes on performance\nDoing method-calls to threads is slower than when running in a single thread. The greatest benefit comes when there is heavy computations to be made.\n\nThis table shows measured round-trip times of [just calling a method](https://github.com/nytamin/threadedClass/blob/master/performance-test/index.js):\n\n| Platform | API used | Avg. time per call |\n|--|--|--|\n| NodeJS 8.17    | Single-thread mode   |   0.000200 ms per call   |\n| NodeJS 8.17    | Child process        | **0.090000** ms per call |\n| NodeJS 10.15   | Single-thread mode   |   0.000078 ms per call   |\n| NodeJS 10.15   | Child process        | **0.076000** ms per call |\n| NodeJS 10.15   | Worker-threads       | **0.045000** ms per call |\n| NodeJS 12.22   | Single-thread mode   |   0.000064 ms per call   |\n| NodeJS 12.22   | Worker-threads       | **0.053000** ms per call |\n| NodeJS 14.18   | Single-thread mode   |   0.000069 ms per call   |\n| NodeJS 14.18   | Worker-threads       | **0.055000** ms per call |\n| NodeJS 16.14   | Single-thread mode   |   0.000072 ms per call   |\n| NodeJS 16.14   | Worker-threads       | **0.052000** ms per call |\n| Browser (Chrome 99) | Single-thread mode   |   0.002500 ms per call   |\n| Browser (Chrome 99) | Web-workers          | **0.094202** ms per call |\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnytamin%2Fthreadedclass","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnytamin%2Fthreadedclass","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnytamin%2Fthreadedclass/lists"}