{"id":13447884,"url":"https://github.com/satya164/web-worker-proxy","last_synced_at":"2025-04-09T14:14:15.788Z","repository":{"id":66198927,"uuid":"145920783","full_name":"satya164/web-worker-proxy","owner":"satya164","description":"A better way of working with web workers","archived":false,"fork":false,"pushed_at":"2019-10-17T18:41:46.000Z","size":623,"stargazers_count":234,"open_issues_count":5,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-02T12:53:42.678Z","etag":null,"topics":["browser","hacktoberfest","proxy","web-worker"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/satya164.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2018-08-24T00:15:24.000Z","updated_at":"2025-03-22T21:33:19.000Z","dependencies_parsed_at":"2023-04-01T05:32:32.887Z","dependency_job_id":null,"html_url":"https://github.com/satya164/web-worker-proxy","commit_stats":{"total_commits":43,"total_committers":3,"mean_commits":"14.333333333333334","dds":0.09302325581395354,"last_synced_commit":"31d1be016b7603ef7b154e1d97088c41ce8858f5"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/satya164%2Fweb-worker-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/satya164%2Fweb-worker-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/satya164%2Fweb-worker-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/satya164%2Fweb-worker-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/satya164","download_url":"https://codeload.github.com/satya164/web-worker-proxy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248054193,"owners_count":21039952,"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":["browser","hacktoberfest","proxy","web-worker"],"created_at":"2024-07-31T05:01:29.450Z","updated_at":"2025-04-09T14:14:15.763Z","avatar_url":"https://github.com/satya164.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# web-worker-proxy\n\n[![Build Status][build-badge]][build]\n[![Code Coverage][coverage-badge]][coverage]\n[![MIT License][license-badge]][license]\n[![Version][version-badge]][package]\n[![Bundle size (minified + gzip)][bundle-size-badge]][bundle-size]\n\nA better way of working with web workers. Uses [JavaScript Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) to make communcation with web workers similar to interacting with normal objects.\n\n## Why\n\nWeb workers are great to offload work to a different thread in browsers. However, the messaging based API is not very easy to work with. This library makes working with web workers similar to how you'd interact with a local object, thanks to the power of proxies.\n\n## Features\n\n- Access and set properties on the proxied object asynchronously, even nested ones\n- Call functions on the proxied object and receive the result asynchronously\n- Pass callbacks (limited functionality) to the worker which can be called asynchronously\n- Receive thrown errors without extra handling for serialization\n\n## Installation\n\n```sh\nnpm install web-worker-proxy\n```\n\nor\n\n```sh\nyarn add web-worker-proxy\n```\n\n## Usage\n\nFirst, we need to wrap our worker:\n\n```js\n// app.js\nimport { create } from 'web-worker-proxy';\n\nconst worker = create(new Worker('worker.js'));\n```\n\nInside the web worker, we need to wrap the target object to proxy it:\n\n```js\n// worker.js\nimport { proxy } from 'web-worker-proxy';\n\nproxy({\n  name: { first: 'John', last: 'Doe' },\n  add: (a, b) =\u003e a + b,\n});\n```\n\nNow we can access properties, call methods etc. by using the `await` keyword, or passing a callback to `then`:\n\n```js\nconsole.log(await worker.name.first); // 'John'\n\n// or\n\nworker.name.first.then(result =\u003e {\n  console.log(result); // 'John'\n});\n```\n\nAccessing properties is lazy, so the actual operation doesn't start until you await the value or call `then` on it.\n\n## Supported operations\n\n### Accessing a property\n\nYou can access any serializable properties on the proxied object asynchronously:\n\n```js\n// Serializable values\nconsole.log(await worker.name);\n\n// Nested properties\nconsole.log(await worker.name.first);\n\n// Even array indices\nconsole.log(await worker.items[0]);\n```\n\nWhen accessing a property, you'll get a thenable (an object with a `then` method), not an normal promise. If you want to use it as a normal promise, wrap it in `Promise.resolve`:\n\n```js\n// Now you can call `catch` on the promise\nPromise.resolve(worker.name.first).catch(error =\u003e {\n  console.log(error);\n});\n```\n\n### Adding or updating a property\n\nYou can add a new property on the proxied object, or create a new one. It can be a nested property too:\n\n```js\nworker.thisisawesome = {};\nworker.thisisawesome.stuff = 42;\n```\n\n### Calling methods\n\nYou can call methods on the proxied object, and pass any serializable arguments to it. The method will return a promise which will resolve to the value returned in the worker. You can also catch errors thrown from it:\n\n```js\ntry {\n  const result = await worker.add(2, 3);\n} catch (e) {\n  console.log(e);\n}\n```\n\nThe method on the proxied object can return any serializable value or a promise which returns a serializable value.\n\nIt's also possible to pass callbacks to methods, with some limitations:\n\n- The arguments to the callback function must be serializable\n- The callback functions are one-way, which means, you cannot return a value from a callback function\n- The callback functions must be direct arguments to the method, it cannot be nested inside an object\n\n```js\nworker.methods.validate(result =\u003e {\n  console.log(result);\n});\n```\n\nTo prevent memory leaks, callbacks are cleaned up as soon as they are called. Which means, if your callback is supposed to be called multiple times, it won't work. However, you can persist a callback function for as long as you want with the `persist` helper. Persisting a function keeps around the event listeners. You must call `dispose` once the function is no longer needed so that they can be cleaned up.\n\n```js\nimport { persist } from 'web-worker-proxy';\n\nconst callback = persist(result =\u003e {\n  if (result.done) {\n    callback.dispose();\n  } else {\n    console.log(result);\n  }\n});\n\nworker.subscribe(callback);\n```\n\n## API\n\n### `create(worker: Worker)`\n\nCreate a proxy object which wraps the worker and allows you to interact with the proxied object inside the worker. It can take any object which implements the `postMessage` interface and the event interface (`addEventListener` and `removeListener`).\n\n### `proxy(object: Object, target?: Worker = self)`\n\nProxy an object so it can be interacted with. The first argument is the object to proxy, and the second argument is an object which implements the `postMessage` interface and the event interface, it defaults to `self`. It returns an object with a `dispose` method to dispose the proxy.\n\nThere can be only one proxy active for a given target at a time. To proxy a different object, we first need to dispose the previous proxy first by using the `disposed` method.\n\n### `persist(function: Function)`\n\nWrap a function so it can be persisted when passed as a callback. Returns an object with a `dispose` method to dispose the persisted function.\n\n## Browser compatibility\n\nThe library expects the `Proxy` and `WeakMap` constructors to be available globally. If you are using a browser which doesn't support these features, make sure to load appropriate polyfills.\n\nThe following environments support these features natively: Google Chrome \u003e= 49, Microsoft Edge \u003e= 12, Mozilla Firefox \u003e= 18, Opera \u003e= 36, Safari \u003e= 10, Node \u003e= 6.0.0.\n\n## Limitations\n\n- Since workers run in a separate thread, all operations are asynchronous, and will return thenables\n- The transferred data needs to be serializable (error objects are handled automatically), most browsers implement the [structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) for transferring data\n- The transferred data is always copied, which means the references will be different, and any mutations won't be visible\n\n## How it works\n\nThe library leverages [proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) to intercept actions such as property access, function call etc., and then the details of the actions are sent to the web worker via the messaging API. The proxied object in the web worker recieves and performs the action, then sends the results back via the messaging API. Every action contains a unique id to distinguish itself from other actions.\n\n## Alternatives\n\n- [comlink](https://github.com/GoogleChromeLabs/comlink)\n- [workway](https://github.com/WebReflection/workway)\n- [workerize](https://github.com/developit/workerize)\n\n## Contributing\n\nWhile developing, you can run the example app and open the console to see your changes:\n\n```sh\nyarn example\n```\n\nMake sure your code passes the unit tests, Flow and ESLint. Run the following to verify:\n\n```sh\nyarn test\nyarn flow\nyarn lint\n```\n\nTo fix formatting errors, run the following:\n\n```sh\nyarn lint -- --fix\n```\n\n\u003c!-- badges --\u003e\n\n[build-badge]: https://img.shields.io/circleci/project/github/satya164/web-worker-proxy/master.svg?style=flat-square\n[build]: https://circleci.com/gh/satya164/web-worker-proxy\n[coverage-badge]: https://img.shields.io/codecov/c/github/satya164/web-worker-proxy.svg?style=flat-square\n[coverage]: https://codecov.io/github/satya164/web-worker-proxy\n[license-badge]: https://img.shields.io/npm/l/web-worker-proxy.svg?style=flat-square\n[license]: https://opensource.org/licenses/MIT\n[version-badge]: https://img.shields.io/npm/v/web-worker-proxy.svg?style=flat-square\n[package]: https://www.npmjs.com/package/web-worker-proxy\n[bundle-size-badge]: https://img.shields.io/bundlephobia/minzip/web-worker-proxy.svg?style=flat-square\n[bundle-size]: https://bundlephobia.com/result?p=web-worker-proxy\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsatya164%2Fweb-worker-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsatya164%2Fweb-worker-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsatya164%2Fweb-worker-proxy/lists"}