GoogleChromeLabs / GoogleChromeLabs/comlink

Feature request: Automatically reject pending requests when proxy is released

Open
#601 3 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
TypeScript
Stars
12.8k
Forks
435
PR merge metrics
No merged PRs in 30d

Description

As it stands (as far as I can tell) comlink does not reject previous requests when closed, so if a proxy is released while you are waiting on a response to a previous call, there is no error, the promise just never resolves. There's no real way to deal with this outside of comlink except to track the state of the worker manually and add something to every function call to reject pending requests when the worker is closed.

Would be fairly simple to add by doing the following:

- When postMessage is called, add the reject(e) callback from the promise to an array.
- Remove this callback from the array on completion.
- When the proxy is released, loop over the array and call all of the rejection callbacks with an error message.

```
function requestResponseMessage(
ep: Endpoint,
msg: Message,
transfers?: Transferable[],
rejectors: ((e: unknown) => void)[], **<-- ADD**
): Promise {
return new Promise((resolve, reject) => { **<-- ADD**
rejectors.push(reject) **<-- ADD**
const id = generateUUID();
ep.addEventListener("message", function l(ev: MessageEvent) {
if (!ev.data || !ev.data.id || ev.data.id !== id) {
return;
}
ep.removeEventListener("message", l as any);
resolve(ev.data);
rejectors.splice(rejectors.indexOf(reject), 1) **<-- ADD**
} as any);
if (ep.start) {
ep.start();
}
ep.postMessage({ id, ...msg }, transfers);
});
}

```

```
function createProxy(
ep: Endpoint,
path: (string | number | symbol)[] = [],
target: object = function () {}
): Remote {
let isProxyReleased = false;
let rejectors = new Array<(e: unknown) => void>() **<-- ADD**
const proxy = new Proxy(target, {
get(_target, prop) {
throwIfProxyReleased(isProxyReleased);
if (prop === releaseProxy) {
return () => {
rejectors.forEach(rejector => rejector("This proxy has been released.")) **<-- ADD**
return requestResponseMessage(ep, {
type: MessageType.RELEASE,
path: path.map((p) => p.toString()),
}).then(() => {
closeEndPoint(ep);
isProxyReleased = true;
});
};
}
```

Of course anytime requestResponseMessage is called, the rejectors array would need to be passed (didnt bother to include).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.