{"id":13527021,"url":"https://github.com/GoogleChromeLabs/clooney","last_synced_at":"2025-04-01T09:30:57.729Z","repository":{"id":29658682,"uuid":"122394858","full_name":"GoogleChromeLabs/clooney","owner":"GoogleChromeLabs","description":"Clooney is an actor library for the web. Use workers without thinking about workers.","archived":false,"fork":false,"pushed_at":"2025-03-24T06:00:00.000Z","size":754,"stargazers_count":1419,"open_issues_count":35,"forks_count":52,"subscribers_count":22,"default_branch":"master","last_synced_at":"2025-03-24T06:33:21.063Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GoogleChromeLabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-21T21:18:22.000Z","updated_at":"2025-03-17T14:37:25.000Z","dependencies_parsed_at":"2023-09-27T15:52:03.157Z","dependency_job_id":"257cdc98-32b4-40bb-8981-7e9a7cb003f0","html_url":"https://github.com/GoogleChromeLabs/clooney","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleChromeLabs%2Fclooney","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleChromeLabs%2Fclooney/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleChromeLabs%2Fclooney/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleChromeLabs%2Fclooney/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GoogleChromeLabs","download_url":"https://codeload.github.com/GoogleChromeLabs/clooney/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246615924,"owners_count":20806029,"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","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":[],"created_at":"2024-08-01T06:01:39.427Z","updated_at":"2025-04-01T09:30:57.326Z","avatar_url":"https://github.com/GoogleChromeLabs.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","Tools, Applications, Libraries, Frameworks","🔧 Utilities \u0026 Miscellaneous","Web Worker"],"sub_categories":["Runner"],"readme":"# Clooney\nClooney is an actor (ayooo) library for the web. Classes given to Clooney will be instantiated and run in a worker, keeping the main thread responsive.\n\n\u003e ⚠️ **Caveat:** The class cannot rely on its surrounding scope, since it is executed in an isolated context. This might change once workers support ES6 modules.\n\n## Quickstart\nAn example says more than 1000 words:\n\n```html\n\u003cscript src=\"/clooney.bundle.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  (async function() {\n    class MyRemoteClass {\n      doExpensiveCalculation(a, b) {\n        return a + b;\n      }\n    }\n\n    const instance = await Clooney.spawn(MyRemoteClass);\n    console.log(await instance.doExpensiveCalculation(5, 23));\n  })();\n\u003c/script\u003e\n```\n\nI’m collecting more examples of Clooney in action in [this Glitch](https://clooney-examples.glitch.me/).\n\n## Browser support\n\nClooney uses [Comlink] under the hood, and so inherits its browser compatibility matrix.\n\n![Chrome 56+](https://img.shields.io/badge/Chrome-56+-green.svg?style=flat-square)\n![Edge 15+](https://img.shields.io/badge/Edge-15+-green.svg?style=flat-square)\n![Firefox 52+](https://img.shields.io/badge/Firefox-52+-green.svg?style=flat-square)\n![Opera 43+](https://img.shields.io/badge/Opera-43+-green.svg?style=flat-square)\n![Safari 10.1+](https://img.shields.io/badge/Safari-10.1+-green.svg?style=flat-square)\n![Samsung Internet 6.0+](https://img.shields.io/badge/Samsung_Internet-6.0+-green.svg?style=flat-square)\n\nBrowsers without [ES6 Proxy] support can use the [proxy-polyfill].\n\n## Events and Functions\nFunctions and events are not transferable (i.e. can’t be sent from to a worker), but Clooney has special handling for them:\n\n```js\nclass MyRemoteClass {\n  onClick(remoteEvent) {\n    // … react to click …\n  }\n}\n\nconst instance = await Clooney.spawn(MyRemoteClass);\nconst button = document.querySelector('button');\nbutton.addEventListener('click', instance.onClick.bind(instance));\n```\n\nThe `remoteEvent` object is a mangled version of the original event to make it transferable:\n\n```js\nconst remoteEvent = {\n  targetId, // = event.target.id\n  targetClassList, // = [...event.target.classList]\n  detail, // = event.detail\n  data // = event.data\n};\n```\n\n## Promises and async methods\nClooney handles promises (and therefore, async methods) automatically:\n\n```js\nclass Actor {\n  timeoutThing() {\n    return new Promise(resolve =\u003e setTimeout(_ =\u003e resolve('ohai'), 1000));\n  }\n}\n\nconst instance = await strategy.spawn(Actor);\nalert(await instance.timeoutThing()); // Will alert() after 1 second\n```\n\n## API\nClooney’s job is to take _actors_ (class definitions) and _spawn_ those actors in _containers_ ([Web Workers][Web Worker]). You can use that instance as if it was a local instance (this is magic provided by [Comlink]).\n\n### `Clooney.spawn(class, constructorArgs)`\nThis call is equivalent to `Clooney.defaultStrategy.spawn(class, constructorArgs)`. Clooney creates an instance of `RoundRobinStrategy` as the default strategy.\n\n### Strategies\nStrategies decide how many containers are spun up and where a new instance is created.\n\n```typescript\nexport interface Strategy {\n  /**\n   * `spawn` instantiates the given actor in an actor container of the strategy’s choice.\n   * @returns The return type is the type as T, but every method is implicitly async.\n   */\n  spawn\u003cT\u003e(actor: new () =\u003e T, constructorArgs: any[], opts: Object): Promise\u003cT\u003e;\n  /**\n   * `terminate` calls `terminate()` on all existing containers of the strategy.\n   */\n  terminate(): Promise\u003cvoid\u003e;\n}\n```\n\n#### `Clooney.RoundRobinStrategy(opts)`\n`RoundRobinStrategy` creates up to n containers and cycles through the containers with every `spawn` call. `RoundRobinStrategy` is the default strategy.\n\n### Strategy Options\n\n- `maxNumContainers`: Maximum number of containers to create (default: 1)\n- `newWorkerFunc`: Asynchronous function that creates a new container (default: `new Worker(Clooney.defaultWorkerSrc)`)\n\n### `Clooney.asRemoteValue(obj)`\n\n`asRemoteValue` marks a value. If a marked value is used as an parameter or return value, it will not be transferred but instead proxied.\n\n## CDN\nIf you want to use Clooney from a CDN, you need to work around the same-origin restrictions that workers have:\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/clooneyjs@0.7.0/clooney.bundle.min.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  async function newWorkerFunc() {\n    const blob = await fetch(Clooney.defaultWorkerSrc).then(resp =\u003e resp.blob())\n    return new Worker(URL.createObjectURL(blob));\n  }\n\n  const strategy = new Clooney.RoundRobinStrategy({newWorkerFunc});\n  // Business as usual using strategy.spawn() ...\n\u003c/script\u003e\n```\n\n[Comlink]: https://github.com/GoogleChromeLabs/comlink\n[Web Worker]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API\n[es6 proxy]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy\n[proxy-polyfill]: https://github.com/GoogleChrome/proxy-polyfill\n\n---\nLicense Apache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGoogleChromeLabs%2Fclooney","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGoogleChromeLabs%2Fclooney","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGoogleChromeLabs%2Fclooney/lists"}