Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/GoogleChromeLabs/clooney
Clooney is an actor library for the web. Use workers without thinking about workers.
https://github.com/GoogleChromeLabs/clooney
Last synced: 6 days ago
JSON representation
Clooney is an actor library for the web. Use workers without thinking about workers.
- Host: GitHub
- URL: https://github.com/GoogleChromeLabs/clooney
- Owner: GoogleChromeLabs
- License: apache-2.0
- Created: 2018-02-21T21:18:22.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2024-08-28T08:58:32.000Z (2 months ago)
- Last Synced: 2024-08-28T10:14:36.833Z (2 months ago)
- Language: JavaScript
- Homepage:
- Size: 734 KB
- Stars: 1,420
- Watchers: 23
- Forks: 52
- Open Issues: 32
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING
- License: LICENSE
- Codeowners: CODEOWNERS
Awesome Lists containing this project
- awesome-naming - clooney - A JavaScript library implementing the actor model for concurrent computation. The term is a reference to George Clooney who is also an actor. (Tools, Applications, Libraries, Frameworks)
- awesome-list - clooney
README
# Clooney
Clooney 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.> ⚠️ **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.
## Quickstart
An example says more than 1000 words:```html
(async function() {
class MyRemoteClass {
doExpensiveCalculation(a, b) {
return a + b;
}
}const instance = await Clooney.spawn(MyRemoteClass);
console.log(await instance.doExpensiveCalculation(5, 23));
})();```
I’m collecting more examples of Clooney in action in [this Glitch](https://clooney-examples.glitch.me/).
## Browser support
Clooney uses [Comlink] under the hood, and so inherits its browser compatibility matrix.
![Chrome 56+](https://img.shields.io/badge/Chrome-56+-green.svg?style=flat-square)
![Edge 15+](https://img.shields.io/badge/Edge-15+-green.svg?style=flat-square)
![Firefox 52+](https://img.shields.io/badge/Firefox-52+-green.svg?style=flat-square)
![Opera 43+](https://img.shields.io/badge/Opera-43+-green.svg?style=flat-square)
![Safari 10.1+](https://img.shields.io/badge/Safari-10.1+-green.svg?style=flat-square)
![Samsung Internet 6.0+](https://img.shields.io/badge/Samsung_Internet-6.0+-green.svg?style=flat-square)Browsers without [ES6 Proxy] support can use the [proxy-polyfill].
## Events and Functions
Functions and events are not transferable (i.e. can’t be sent from to a worker), but Clooney has special handling for them:```js
class MyRemoteClass {
onClick(remoteEvent) {
// … react to click …
}
}const instance = await Clooney.spawn(MyRemoteClass);
const button = document.querySelector('button');
button.addEventListener('click', instance.onClick.bind(instance));
```The `remoteEvent` object is a mangled version of the original event to make it transferable:
```js
const remoteEvent = {
targetId, // = event.target.id
targetClassList, // = [...event.target.classList]
detail, // = event.detail
data // = event.data
};
```## Promises and async methods
Clooney handles promises (and therefore, async methods) automatically:```js
class Actor {
timeoutThing() {
return new Promise(resolve => setTimeout(_ => resolve('ohai'), 1000));
}
}const instance = await strategy.spawn(Actor);
alert(await instance.timeoutThing()); // Will alert() after 1 second
```## API
Clooney’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]).### `Clooney.spawn(class, constructorArgs)`
This call is equivalent to `Clooney.defaultStrategy.spawn(class, constructorArgs)`. Clooney creates an instance of `RoundRobinStrategy` as the default strategy.### Strategies
Strategies decide how many containers are spun up and where a new instance is created.```typescript
export interface Strategy {
/**
* `spawn` instantiates the given actor in an actor container of the strategy’s choice.
* @returns The return type is the type as T, but every method is implicitly async.
*/
spawn(actor: new () => T, constructorArgs: any[], opts: Object): Promise;
/**
* `terminate` calls `terminate()` on all existing containers of the strategy.
*/
terminate(): Promise;
}
```#### `Clooney.RoundRobinStrategy(opts)`
`RoundRobinStrategy` creates up to n containers and cycles through the containers with every `spawn` call. `RoundRobinStrategy` is the default strategy.### Strategy Options
- `maxNumContainers`: Maximum number of containers to create (default: 1)
- `newWorkerFunc`: Asynchronous function that creates a new container (default: `new Worker(Clooney.defaultWorkerSrc)`)### `Clooney.asRemoteValue(obj)`
`asRemoteValue` marks a value. If a marked value is used as an parameter or return value, it will not be transferred but instead proxied.
## CDN
If you want to use Clooney from a CDN, you need to work around the same-origin restrictions that workers have:```html
async function newWorkerFunc() {
const blob = await fetch(Clooney.defaultWorkerSrc).then(resp => resp.blob())
return new Worker(URL.createObjectURL(blob));
}const strategy = new Clooney.RoundRobinStrategy({newWorkerFunc});
// Business as usual using strategy.spawn() ...```
[Comlink]: https://github.com/GoogleChromeLabs/comlink
[Web Worker]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
[es6 proxy]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
[proxy-polyfill]: https://github.com/GoogleChrome/proxy-polyfill---
License Apache-2.0