Open qnku opened 1 year ago
Maybe related to #39079 with the need to get the proper status codes from negotiation.
This looks like a potential good first issue for me. I would like to collaborate, If I can, there is some doc related about how to start?
Background and Motivation
This is about the JavaScript SignalR client ("dotnet/aspnetcore/src/SignalR/clients/ts/signalr").
The
HubConnection
class may throw errors (i.e. with the message "Error: Server returned handshake error: Handshake was canceled."). These errors propagate up to the application layer. Currently, it is challenging to reliably identify these errors as originating from SignalR because theHubConnection
class creates plainError
types without any distinct characteristics. In our scenario, we have implemented a global error handler that notifies users visually when an unhandled error occurs.However, since SignalR errors can occur sporadically and independently of user actions, it is desirable to filter out these errors. Presently, we achieve this by checking if the error's message property contains a specific string, like the one mentioned earlier. Unfortunately, this approach is not reliable, as the error message can change at any time, and there are multiple variations.
The proposal is to follow best practices and define a custom error type and/or set the cause field for library specific errors. This will allow library consumer to properly catch errors thrown by the library.
From MDN
Interestingly, the Error.ts file already contains some error types; however, they seem to be exclusively used by the HTTP wrapper, leaving the other SignalR errors unaccounted for.
Proposed API
1) Add a new error class (derived from
Error
) and set thename
field 2) Change code that usesnew Error
to usenew HubConnectionError
insteadUnfortunately, I don't understand why the existing error types use a strange prototype workaround. I have read that it is supposed to make
instanceof
work correctly. However, in my tests, that didn't change anything, asinstanceof
checks still don't work. Therefore, it seems like it doesn't do anything? I'd be interested in the background on that.Due to this reason, I have not followed this pattern in this proposal. Instead, the name field in the constructor is set. While not perfect (i.e. other error types might use the same name), setting the name field is a common practice and essential for making the error identifiable during a catch.
Usage Examples
Now we can properly catch the error by checking the
name
property that was set in the error constructor. Usinginstanceof
for error checks is known to be problematic so we avoid it.Alternative Designs
As an alternative to introducing new error types, we could populate the
cause
field mentioned earlier with a value or object structure that allows us to identify these error instances as SignalR errors.Risks
cause
property is not available in "es2019" (introduced in es2022), it is likely unsuitable as it won't function on older browsers.