Skip to content

Commit 88858d0

Browse files
committed
Changes per PR
1 parent aeb42fd commit 88858d0

File tree

2 files changed

+72
-80
lines changed

2 files changed

+72
-80
lines changed

src/Components/Browser.JS/src/Boot.Server.ts

Lines changed: 64 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -8,95 +8,84 @@ import { renderBatch } from './Rendering/Renderer';
88
import { fetchBootConfigAsync, loadEmbeddedResourcesAsync } from './BootCommon';
99
import { CircuitHandler } from './Platform/Circuits/CircuitHandler';
1010

11-
async function boot(reconnect: boolean = false) {
12-
const circuitHandlers = new Array<CircuitHandler>();
11+
async function boot() {
12+
const circuitHandlers: CircuitHandler[] = [];
1313
window['Blazor'].addCircuitHandler = (circuitHandler: CircuitHandler) => circuitHandlers.push(circuitHandler);
1414

15-
await startCicuit();
16-
17-
async function startCicuit(): Promise<void> {
18-
// In the background, start loading the boot config and any embedded resources
19-
const embeddedResourcesPromise = fetchBootConfigAsync().then(bootConfig => {
20-
return loadEmbeddedResourcesAsync(bootConfig);
21-
});
22-
23-
const initialConnection = await initializeConnection();
24-
25-
// Ensure any embedded resources have been loaded before starting the app
26-
await embeddedResourcesPromise;
27-
const circuitId = await initialConnection.invoke<string>(
28-
'StartCircuit',
29-
uriHelperFunctions.getLocationHref(),
30-
uriHelperFunctions.getBaseURI()
31-
);
15+
// In the background, start loading the boot config and any embedded resources
16+
const embeddedResourcesPromise = fetchBootConfigAsync().then(bootConfig => {
17+
return loadEmbeddedResourcesAsync(bootConfig);
18+
});
19+
20+
const initialConnection = await initializeConnection(circuitHandlers);
21+
22+
// Ensure any embedded resources have been loaded before starting the app
23+
await embeddedResourcesPromise;
24+
const circuitId = await initialConnection.invoke<string>(
25+
'StartCircuit',
26+
uriHelperFunctions.getLocationHref(),
27+
uriHelperFunctions.getBaseURI()
28+
);
29+
30+
window['Blazor'].reconnect = async () => {
31+
const reconnection = await initializeConnection(circuitHandlers);
32+
if (!await reconnection.invoke<Boolean>('ConnectCircuit', circuitId)) {
33+
throw new Error('Failed to reconnect to the server. The supplied circuitId is no longer valid');
34+
}
3235

33-
window['Blazor'].reconnect = async () => {
34-
const reconnection = await initializeConnection();
35-
if (!await reconnection.invoke<Boolean>('ConnectCircuit', circuitId)) {
36-
throw "Failed to reconnect to the server";
37-
}
36+
circuitHandlers.forEach(h => h.onConnectionUp && h.onConnectionUp());
37+
};
3838

39-
circuitHandlers.forEach(h => h.onConnectionUp());
40-
};
39+
circuitHandlers.forEach(h => h.onConnectionUp && h.onConnectionUp());
40+
}
4141

42-
circuitHandlers.forEach(h => h.onConnectionUp());
43-
}
44-
45-
async function initializeConnection(): Promise<signalR.HubConnection> {
46-
const connection = new signalR.HubConnectionBuilder()
47-
.withUrl('_blazor')
48-
.withHubProtocol(new MessagePackHubProtocol())
49-
.configureLogging(signalR.LogLevel.Information)
50-
.build();
51-
connection.on('JS.BeginInvokeJS', DotNet.jsCallDispatcher.beginInvokeJSFromDotNet);
52-
connection.on('JS.RenderBatch', (browserRendererId: number, renderId: number, batchData: Uint8Array) => {
53-
try {
54-
renderBatch(browserRendererId, new OutOfProcessRenderBatch(batchData));
55-
connection.send('OnRenderCompleted', renderId, null);
56-
}
57-
catch (ex) {
58-
// If there's a rendering exception, notify server *and* throw on client
59-
connection.send('OnRenderCompleted', renderId, ex.toString());
60-
throw ex;
61-
}
62-
});
63-
64-
connection.onclose(error => circuitHandlers.forEach(h => h.onConnectionDown(error)));
65-
connection.on('JS.Error', unhandledError.bind(connection));
66-
67-
window['Blazor'].closeConnection = async() => {
68-
await connection.stop();
69-
DotNet.attachDispatcher({
70-
beginInvokeDotNetFromJS: (...args) => {}});
71-
}
42+
async function initializeConnection(circuitHandlers: CircuitHandler[]): Promise<signalR.HubConnection> {
43+
const connection = new signalR.HubConnectionBuilder()
44+
.withUrl('_blazor')
45+
.withHubProtocol(new MessagePackHubProtocol())
46+
.configureLogging(signalR.LogLevel.Information)
47+
.build();
7248

49+
connection.on('JS.BeginInvokeJS', DotNet.jsCallDispatcher.beginInvokeJSFromDotNet);
50+
connection.on('JS.RenderBatch', (browserRendererId: number, renderId: number, batchData: Uint8Array) => {
7351
try {
74-
await connection.start();
52+
renderBatch(browserRendererId, new OutOfProcessRenderBatch(batchData));
53+
connection.send('OnRenderCompleted', renderId, null);
7554
} catch (ex) {
76-
unhandledError.call(connection, ex);
55+
// If there's a rendering exception, notify server *and* throw on client
56+
connection.send('OnRenderCompleted', renderId, ex.toString());
57+
throw ex;
7758
}
59+
});
60+
61+
connection.onclose(error => circuitHandlers.forEach(h => h.onConnectionDown && h.onConnectionDown(error)));
62+
connection.on('JS.Error', error => unhandledError(connection, error));
7863

79-
DotNet.attachDispatcher({
80-
beginInvokeDotNetFromJS: (callId, assemblyName, methodIdentifier, dotNetObjectId, argsJson) => {
81-
connection.send('BeginInvokeDotNetFromJS', callId ? callId.toString() : null, assemblyName, methodIdentifier, dotNetObjectId || 0, argsJson);
82-
}
83-
});
64+
window['Blazor']._internal.forceCloseConnection = connection.stop;
8465

85-
return connection;
66+
try {
67+
await connection.start();
68+
} catch (ex) {
69+
unhandledError(connection, ex);
8670
}
8771

88-
function unhandledError(this: signalR.HubConnection, err) {
89-
console.error(err);
90-
91-
// Disconnect on errors.
92-
//
93-
// TODO: it would be nice to have some kind of experience for what happens when you're
94-
// trying to interact with an app that's disconnected.
95-
//
96-
// Trying to call methods on the connection after its been closed will throw.
97-
if (this) {
98-
this.stop();
72+
DotNet.attachDispatcher({
73+
beginInvokeDotNetFromJS: (callId, assemblyName, methodIdentifier, dotNetObjectId, argsJson) => {
74+
connection.send('BeginInvokeDotNetFromJS', callId ? callId.toString() : null, assemblyName, methodIdentifier, dotNetObjectId || 0, argsJson);
9975
}
76+
});
77+
78+
return connection;
79+
}
80+
81+
function unhandledError(connection: signalR.HubConnection, err: Error) {
82+
console.error(err);
83+
84+
// Disconnect on errors.
85+
//
86+
// Trying to call methods on the connection after its been closed will throw.
87+
if (connection) {
88+
connection.stop();
10089
}
10190
}
10291

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
export abstract class CircuitHandler {
2-
onConnectionUp() : void{
3-
}
1+
export interface CircuitHandler {
2+
/** Invoked when a server connection is established or re-established after a connection failure.
3+
*/
4+
onConnectionUp?() : void;
45

5-
onConnectionDown(error?: Error): void{
6-
}
6+
/** Invoked when a server connection is dropped.
7+
* @param {Error} error Optionally argument containing the error that caused the connection to close (if any).
8+
*/
9+
onConnectionDown?(error?: Error): void;
710
}

0 commit comments

Comments
 (0)