Skip to content

Commit 178374d

Browse files
Make reconnection work more realistically (#12420)
* Support reconnection even if an earlier attempt failed * Add "reload" button to reconnect dialog on failure * Update blazor.*.js
1 parent 330a770 commit 178374d

File tree

5 files changed

+31
-16
lines changed

5 files changed

+31
-16
lines changed

src/Components/Web.JS/dist/Release/blazor.server.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,10 @@ async function initializeConnection(options: BlazorOptions, logger: Logger): Pro
105105
});
106106

107107
connection.onclose(error => !renderingFailed && options.reconnectionHandler!.onConnectionDown(options.reconnectionOptions, error));
108-
connection.on('JS.Error', error => unhandledError(connection, error, logger));
108+
connection.on('JS.Error', error => {
109+
renderingFailed = true;
110+
unhandledError(connection, error, logger);
111+
});
109112

110113
window['Blazor']._internal.forceCloseConnection = () => connection.stop();
111114

@@ -134,7 +137,6 @@ function unhandledError(connection: signalR.HubConnection, err: Error, logger: L
134137
//
135138
// Trying to call methods on the connection after its been closed will throw.
136139
if (connection) {
137-
renderingFailed = true;
138140
connection.stop();
139141
}
140142
}

src/Components/Web.JS/src/Platform/Circuits/DefaultReconnectDisplay.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
99

1010
addedToDom: boolean = false;
1111

12+
reloadParagraph: HTMLParagraphElement;
13+
1214
constructor(dialogId: string, private document: Document) {
1315
this.modal = this.document.createElement('div');
1416
this.modal.id = dialogId;
@@ -29,11 +31,13 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
2931
];
3032

3133
this.modal.style.cssText = modalStyles.join(';');
32-
this.modal.innerHTML = '<h5 style="margin-top: 20px"></h5><button style="margin:5px auto 5px">Retry?</button>';
34+
this.modal.innerHTML = '<h5 style="margin-top: 20px"></h5><button style="margin:5px auto 5px">Retry?</button><p>Alternatively, <a href>reload</a></p>';
3335
this.message = this.modal.querySelector('h5')!;
3436
this.button = this.modal.querySelector('button')!;
37+
this.reloadParagraph = this.modal.querySelector('p')!;
3538

3639
this.button.addEventListener('click', () => window['Blazor'].reconnect());
40+
this.reloadParagraph.querySelector('a')!.addEventListener('click', () => location.reload());
3741
}
3842

3943
show(): void {
@@ -43,6 +47,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
4347
}
4448
this.modal.style.display = 'block';
4549
this.button.style.display = 'none';
50+
this.reloadParagraph.style.display = 'none';
4651
this.message.textContent = 'Attempting to reconnect to the server...';
4752
}
4853

@@ -52,6 +57,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
5257

5358
failed(): void {
5459
this.button.style.display = 'block';
60+
this.reloadParagraph.style.display = 'block';
5561
this.message.textContent = 'Failed to reconnect to the server.';
5662
}
5763
}

src/Components/Web.JS/src/Platform/Circuits/DefaultReconnectionHandler.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,26 @@ import { Logger, LogLevel } from '../Logging/Logger';
66

77
export class DefaultReconnectionHandler implements ReconnectionHandler {
88
private readonly _logger: Logger;
9-
private readonly _overrideDisplay?: ReconnectDisplay;
109
private readonly _reconnectCallback: () => Promise<boolean>;
1110
private _currentReconnectionProcess: ReconnectionProcess | null = null;
11+
private _reconnectionDisplay?: ReconnectDisplay;
1212

1313
constructor(logger: Logger, overrideDisplay?: ReconnectDisplay, reconnectCallback?: () => Promise<boolean>) {
1414
this._logger = logger;
15-
this._overrideDisplay = overrideDisplay;
15+
this._reconnectionDisplay = overrideDisplay;
1616
this._reconnectCallback = reconnectCallback || (() => window['Blazor'].reconnect());
1717
}
1818

1919
onConnectionDown (options: ReconnectionOptions, error?: Error) {
20+
if (!this._reconnectionDisplay) {
21+
const modal = document.getElementById(options.dialogId);
22+
this._reconnectionDisplay = modal
23+
? new UserSpecifiedDisplay(modal)
24+
: new DefaultReconnectDisplay(options.dialogId, document);
25+
}
26+
2027
if (!this._currentReconnectionProcess) {
21-
this._currentReconnectionProcess = new ReconnectionProcess(options, this._logger, this._reconnectCallback, this._overrideDisplay);
28+
this._currentReconnectionProcess = new ReconnectionProcess(options, this._logger, this._reconnectCallback, this._reconnectionDisplay!);
2229
}
2330
}
2431

@@ -34,12 +41,8 @@ class ReconnectionProcess {
3441
readonly reconnectDisplay: ReconnectDisplay;
3542
isDisposed = false;
3643

37-
constructor(options: ReconnectionOptions, private logger: Logger, private reconnectCallback: () => Promise<boolean>, display?: ReconnectDisplay) {
38-
const modal = document.getElementById(options.dialogId);
39-
this.reconnectDisplay = display || (modal
40-
? new UserSpecifiedDisplay(modal)
41-
: new DefaultReconnectDisplay(options.dialogId, document));
42-
44+
constructor(options: ReconnectionOptions, private logger: Logger, private reconnectCallback: () => Promise<boolean>, display: ReconnectDisplay) {
45+
this.reconnectDisplay = display;
4346
this.reconnectDisplay.show();
4447
this.attemptPeriodicReconnection(options);
4548
}

src/Components/test/testassets/ComponentsApp.Server/Pages/Index.cshtml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
configureSignalR: function (builder) {
2121
builder.configureLogging(2); // LogLevel.Information
2222
},
23-
logLevel: 2 // LogLevel.Information
23+
logLevel: 2, // LogLevel.Information
24+
reconnectionOptions: {
25+
maxRetries: 3,
26+
retryIntervalMilliseconds: 2000,
27+
}
2428
}).then(function () {
2529
window['__aspnetcore__testing__blazor__started__'] = true;
2630
});

0 commit comments

Comments
 (0)