`fetchWebSocket` should return a promise
Opened this issue · 3 comments
Currenlty, fetchWebSocket
simply sends a GET
message. The received RESOURCE
is then properly processed, but the function itself does not return this resource. That means users can't await
the requested resource.
How can we fix this?
Well, we could add a .onmessage
handler that calls the return thing, which is awaited. Or does this replace the earlier onmessage
?
EDIT: Fixed, but we could need a more performant solution (see below)
For this to work the websocket functions have to become stateful. A WebsocketClient class with a map of currently requested resources and corresponding callback should do the trick
I've opted for something like this:
const defaultTimeout = 5000;
/** Sends a GET message for some resource over websockets. */
export async function fetchWebSocket(
client: WebSocket,
subject: string,
): Promise<Resource> {
return new Promise((resolve, reject) => {
client.addEventListener('message', function listener(ev) {
const timeoutId = setTimeout(() => {
client.removeEventListener('message', listener);
reject(
new Error(
`Request for subject "${subject}" timed out after ${defaultTimeout}ms.`,
),
);
}, defaultTimeout);
if (ev.data.startsWith('RESOURCE ')) {
parseResourceMessage(ev).forEach(resource => {
// if it is the requested subject, return the resource
if (resource.getSubject() === subject) {
clearTimeout(timeoutId);
client.removeEventListener('message', listener);
resolve(resource);
}
});
}
});
client.send('GET ' + subject);
});
}
I'm having some performance doupts.
Say on init, the user requests about 300 resources using websockets (e.g. when opening a Table or Chat or something).
For each incoming resource, the eventListeners for every other resource are called. This means that we have 300*300 evaluations.
I'm not sure if this will severely impact performance, but I can certainly imagine it will.
One simple way to prevent this, is by only doing the whole eventlistener thing if we know the requesting function is actually waiting for the response. If they aren't await
ing the response, we can simply ignore it.
But how do we know this?
- In
getResourceLoading
(the most commonly used fetch-like function), we could pass an optionnoReturn
or something. If this is present, we use a different function, likefetchWebsocketVoid