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
This commit is contained in:
parent
330a7708c0
commit
178374d228
File diff suppressed because one or more lines are too long
|
|
@ -105,7 +105,10 @@ async function initializeConnection(options: BlazorOptions, logger: Logger): Pro
|
|||
});
|
||||
|
||||
connection.onclose(error => !renderingFailed && options.reconnectionHandler!.onConnectionDown(options.reconnectionOptions, error));
|
||||
connection.on('JS.Error', error => unhandledError(connection, error, logger));
|
||||
connection.on('JS.Error', error => {
|
||||
renderingFailed = true;
|
||||
unhandledError(connection, error, logger);
|
||||
});
|
||||
|
||||
window['Blazor']._internal.forceCloseConnection = () => connection.stop();
|
||||
|
||||
|
|
@ -134,7 +137,6 @@ function unhandledError(connection: signalR.HubConnection, err: Error, logger: L
|
|||
//
|
||||
// Trying to call methods on the connection after its been closed will throw.
|
||||
if (connection) {
|
||||
renderingFailed = true;
|
||||
connection.stop();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
|||
|
||||
addedToDom: boolean = false;
|
||||
|
||||
reloadParagraph: HTMLParagraphElement;
|
||||
|
||||
constructor(dialogId: string, private document: Document) {
|
||||
this.modal = this.document.createElement('div');
|
||||
this.modal.id = dialogId;
|
||||
|
|
@ -29,11 +31,13 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
|||
];
|
||||
|
||||
this.modal.style.cssText = modalStyles.join(';');
|
||||
this.modal.innerHTML = '<h5 style="margin-top: 20px"></h5><button style="margin:5px auto 5px">Retry?</button>';
|
||||
this.modal.innerHTML = '<h5 style="margin-top: 20px"></h5><button style="margin:5px auto 5px">Retry?</button><p>Alternatively, <a href>reload</a></p>';
|
||||
this.message = this.modal.querySelector('h5')!;
|
||||
this.button = this.modal.querySelector('button')!;
|
||||
this.reloadParagraph = this.modal.querySelector('p')!;
|
||||
|
||||
this.button.addEventListener('click', () => window['Blazor'].reconnect());
|
||||
this.reloadParagraph.querySelector('a')!.addEventListener('click', () => location.reload());
|
||||
}
|
||||
|
||||
show(): void {
|
||||
|
|
@ -43,6 +47,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
|||
}
|
||||
this.modal.style.display = 'block';
|
||||
this.button.style.display = 'none';
|
||||
this.reloadParagraph.style.display = 'none';
|
||||
this.message.textContent = 'Attempting to reconnect to the server...';
|
||||
}
|
||||
|
||||
|
|
@ -52,6 +57,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
|||
|
||||
failed(): void {
|
||||
this.button.style.display = 'block';
|
||||
this.reloadParagraph.style.display = 'block';
|
||||
this.message.textContent = 'Failed to reconnect to the server.';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,19 +6,26 @@ import { Logger, LogLevel } from '../Logging/Logger';
|
|||
|
||||
export class DefaultReconnectionHandler implements ReconnectionHandler {
|
||||
private readonly _logger: Logger;
|
||||
private readonly _overrideDisplay?: ReconnectDisplay;
|
||||
private readonly _reconnectCallback: () => Promise<boolean>;
|
||||
private _currentReconnectionProcess: ReconnectionProcess | null = null;
|
||||
private _reconnectionDisplay?: ReconnectDisplay;
|
||||
|
||||
constructor(logger: Logger, overrideDisplay?: ReconnectDisplay, reconnectCallback?: () => Promise<boolean>) {
|
||||
this._logger = logger;
|
||||
this._overrideDisplay = overrideDisplay;
|
||||
this._reconnectionDisplay = overrideDisplay;
|
||||
this._reconnectCallback = reconnectCallback || (() => window['Blazor'].reconnect());
|
||||
}
|
||||
|
||||
onConnectionDown (options: ReconnectionOptions, error?: Error) {
|
||||
if (!this._reconnectionDisplay) {
|
||||
const modal = document.getElementById(options.dialogId);
|
||||
this._reconnectionDisplay = modal
|
||||
? new UserSpecifiedDisplay(modal)
|
||||
: new DefaultReconnectDisplay(options.dialogId, document);
|
||||
}
|
||||
|
||||
if (!this._currentReconnectionProcess) {
|
||||
this._currentReconnectionProcess = new ReconnectionProcess(options, this._logger, this._reconnectCallback, this._overrideDisplay);
|
||||
this._currentReconnectionProcess = new ReconnectionProcess(options, this._logger, this._reconnectCallback, this._reconnectionDisplay!);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -34,12 +41,8 @@ class ReconnectionProcess {
|
|||
readonly reconnectDisplay: ReconnectDisplay;
|
||||
isDisposed = false;
|
||||
|
||||
constructor(options: ReconnectionOptions, private logger: Logger, private reconnectCallback: () => Promise<boolean>, display?: ReconnectDisplay) {
|
||||
const modal = document.getElementById(options.dialogId);
|
||||
this.reconnectDisplay = display || (modal
|
||||
? new UserSpecifiedDisplay(modal)
|
||||
: new DefaultReconnectDisplay(options.dialogId, document));
|
||||
|
||||
constructor(options: ReconnectionOptions, private logger: Logger, private reconnectCallback: () => Promise<boolean>, display: ReconnectDisplay) {
|
||||
this.reconnectDisplay = display;
|
||||
this.reconnectDisplay.show();
|
||||
this.attemptPeriodicReconnection(options);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,11 @@
|
|||
configureSignalR: function (builder) {
|
||||
builder.configureLogging(2); // LogLevel.Information
|
||||
},
|
||||
logLevel: 2 // LogLevel.Information
|
||||
logLevel: 2, // LogLevel.Information
|
||||
reconnectionOptions: {
|
||||
maxRetries: 3,
|
||||
retryIntervalMilliseconds: 2000,
|
||||
}
|
||||
}).then(function () {
|
||||
window['__aspnetcore__testing__blazor__started__'] = true;
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue