1 | # Comlink
|
2 |
|
3 | Comlink’s goal is to make [WebWorkers][webworker] enjoyable. Comlink removes the mental barrier of thinking about `postMessage` and hides the fact that you are working with workers.
|
4 |
|
5 | > Note: Comlink’s goal is to be a building-block for higher-level abstraction libraries. For example, take a look at [Clooney].
|
6 |
|
7 | ```js
|
8 | // main.js
|
9 | const MyClass = Comlink.proxy(new Worker('worker.js'));
|
10 | // `instance` is an instance of `MyClass` that lives in the worker!
|
11 | const instance = await new MyClass();
|
12 | await instance.logSomething(); // logs “myValue = 42”
|
13 | ```
|
14 |
|
15 | ```js
|
16 | // worker.js
|
17 | const myValue = 42;
|
18 | class MyClass {
|
19 | logSomething() {
|
20 | console.log(`myValue = ${myValue}`);
|
21 | }
|
22 | }
|
23 | Comlink.expose(MyClass, self);
|
24 | ```
|
25 |
|
26 | ## Browsers support & bundle size
|
27 |
|
28 | ![Chrome 56+](https://img.shields.io/badge/Chrome-56+-green.svg?style=flat-square)
|
29 | ![Edge 15+](https://img.shields.io/badge/Edge-15+-green.svg?style=flat-square)
|
30 | ![Firefox 52+](https://img.shields.io/badge/Firefox-52+-green.svg?style=flat-square)
|
31 | ![Opera 43+](https://img.shields.io/badge/Opera-43+-green.svg?style=flat-square)
|
32 | ![Safari 10.1+](https://img.shields.io/badge/Safari-10.1+-green.svg?style=flat-square)
|
33 | ![Samsung Internet 6.0+](https://img.shields.io/badge/Samsung_Internet-6.0+-green.svg?style=flat-square)
|
34 |
|
35 | Browsers without [ES6 Proxy] support can use the [proxy-polyfill].
|
36 |
|
37 | **Size**: ~3.9k, ~1.6k gzip’d
|
38 |
|
39 | ## Introduction
|
40 |
|
41 | WebWorkers are a web API that allow you to run code in a separate thread. To communicate with another thread, WebWorkers offer the `postMessage` API. You can send messages in form of [transferable] JavaScript objects using `myWorker.postMessage(someObject)`, triggering a `message` event inside the worker.
|
42 |
|
43 | Comlink turns this messaged-based API into a something more developer-friendly: Values from one thread can be used within the other thread (and vice versa) just like local values.
|
44 |
|
45 | Comlink can be used with anything that offers `postMessage` like windows, iframes and ServiceWorkers.
|
46 |
|
47 | ## Download
|
48 |
|
49 | You can download Comlink from the [dist folder][dist]. Alternatively, you can
|
50 | install it via npm
|
51 |
|
52 | ```
|
53 | $ npm install --save comlinkjs
|
54 | ```
|
55 |
|
56 | or use a CDN like [delivrjs]:
|
57 |
|
58 | ```
|
59 | https://cdn.jsdelivr.net/npm/comlinkjs@3.0.3/umd/comlink.js
|
60 | ```
|
61 |
|
62 | ## Examples
|
63 |
|
64 | There’s a collection of examples in the [examples directory][examples].
|
65 |
|
66 | ## API
|
67 |
|
68 | The Comlink module exports 3 functions:
|
69 |
|
70 | ### `Comlink.proxy(endpoint)`
|
71 |
|
72 | > Returns the value that is exposed on the other side of `endpoint`.
|
73 |
|
74 | `proxy` creates an ES6 proxy and sends all operations performed on that proxy through `endpoint`. `endpoint` can be a `Window`, a `Worker` or a `MessagePort`.\* The other endpoint of the channel should be passed to `Comlink.expose`.
|
75 |
|
76 | If you invoke function, all parameters will be structurally cloned or transferred if they are [transferable]. If you want to pass a function as a parameters (e.g. callbacks), make sure to use `proxyValue` (see below). Same applies to the return value of a function.
|
77 |
|
78 | \*) Technically it can be any object with `postMessage`, `addEventListener` and
|
79 | `removeEventListener`.
|
80 |
|
81 | ### `Comlink.expose(obj, endpoint)`
|
82 |
|
83 | > Exposes `obj` to `endpoint`. Use `Comlink.proxy` on the other end of `endpoint`.
|
84 |
|
85 | `expose` is the counter-part to `proxy`. It listens for RPC messages on `endpoint` and applies the operations to `obj`. Return values of functions will be structurally cloned or transfered if they are [transferable].
|
86 |
|
87 | ### `Comlink.proxyValue(value)`
|
88 |
|
89 | > Makes sure a parameter or return value is proxied, not copied.
|
90 |
|
91 | By default, all parameters to a function are copied (structural clone):
|
92 |
|
93 | ```js
|
94 | // main.js
|
95 | const api = Comlink.proxy(new Worker('worker.js'));
|
96 | const obj = {x: 0};
|
97 | await api.setXto4(obj);
|
98 | console.log(obj.x); // logs 0
|
99 | ```
|
100 |
|
101 | The worker receives a copy of `obj`, so any mutation of `obj` done by the worker won’t affect the original object. If the value should _not_ be copied but instead be proxied, use `Comlink.proxyValue`:
|
102 |
|
103 | ```diff
|
104 | - await api.setXto4(obj);
|
105 | + await api.setXto4(Comlink.proxyValue(obj));
|
106 | ```
|
107 |
|
108 | `console.log(obj.x)` will now log 4.
|
109 |
|
110 | Keep in mind that functions cannot be copied. Unless they are used in combination with `Comlink.proxyValue`, they will get discarded during copy.
|
111 |
|
112 | [clooney]: https://github.com/GoogleChromeLabs/clooney
|
113 | [webworker]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
|
114 | [umd]: https://github.com/umdjs/umd
|
115 | [transferable]: https://developer.mozilla.org/en-US/docs/Web/API/Transferable
|
116 | [messageport]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort
|
117 | [examples]: https://github.com/GoogleChromeLabs/comlink/tree/master/docs/examples
|
118 | [dist]: https://github.com/GoogleChromeLabs/comlink/tree/master/dist
|
119 | [delivrjs]: https://cdn.jsdelivr.net/
|
120 | [es6 proxy]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
|
121 | [proxy-polyfill]: https://github.com/GoogleChrome/proxy-polyfill
|
122 |
|
123 | ---
|
124 |
|
125 | License Apache-2.0
|