refactor: use try catch around all webContent.load(url)

This commit is contained in:
林一二 2021-08-07 22:00:19 +08:00
parent fd72bf5a57
commit af1bb54868
5 changed files with 47 additions and 20 deletions

View file

@ -315,7 +315,9 @@
"InitWikiGitSyncedWikiNoGitUserInfoErrorDescription": "E-6 初始化同步到云端的笔记仓库需要你选择一个云端的 git 仓库地址,还有提供相应云服务的认证凭证,然而目前没有获得这些信息。",
"MainWindowMissing": "E-7 程序无法获取主窗口信息,无法正常运行。",
"WorkspaceFailedToLoadError": "E-8 工作区加载失败错误",
"WorkspaceFailedToLoadErrorDescription": "E-8 工作区对应的Wiki网页加载失败了原因有很多但基本是因为程序Bug"
"WorkspaceFailedToLoadErrorDescription": "E-8 工作区对应的Wiki网页加载失败了原因有很多但基本是因为程序Bug",
"ViewLoadUrlError": "E-9 网页加载失败错误",
"ViewLoadUrlErrorDescription": "E-9 工作区对应的Wiki网页加载失败了但即将重试"
},
"Loading": "加载中",
"Yes": "是的",

View file

@ -1 +1 @@
export const LOAD_VIEW_MAX_RETRIES = 3;
export const LOAD_VIEW_MAX_RETRIES = 10;

View file

@ -0,0 +1,9 @@
import i18n from '@services/libs/i18n';
export class ViewLoadUrlError extends Error {
constructor(initialUrl: string, retryTimes?: number, additionalMessage = '') {
super();
this.name = i18n.t('Error.ViewLoadUrlError');
this.message = `${i18n.t('Error.ViewLoadUrlErrorDescription')} initialUrl: ${initialUrl}, retryTimes: ${retryTimes ?? 'undefined'} ${additionalMessage}`;
}
}

View file

@ -22,6 +22,7 @@ import { IViewService } from './interface';
import { SupportedStorageServices } from '@services/types';
import { getLocalHostUrlWithActualIP, replaceUrlPortWithSettingPort } from '@services/libs/url';
import { logger } from '@services/libs/log';
import { ViewLoadUrlError } from './error';
@injectable()
export class View implements IViewService {
@ -251,18 +252,33 @@ export class View implements IViewService {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
replaceUrlPortWithSettingPort((rememberLastPageVisited && workspace.lastUrl) || workspace.homeUrl, workspace.port),
);
setupViewEventHandlers(view, browserWindow, { shouldPauseNotifications: this.shouldPauseNotifications, workspace, sharedWebPreferences, initialUrl });
// try catch loadUrl, other wise it will throw unhandled promise rejection Error: ERR_CONNECTION_REFUSED (-102) loading 'http://localhost:5212/
// we will set `didFailLoadErrorMessage`, and `didFailLoadTimes < LOAD_VIEW_MAX_RETRIES` in `setupViewEventHandlers`, it will set didFailLoadErrorMessage, and we throw actuarial error after that
try {
await view.webContents.loadURL(initialUrl);
const unregisterContextMenu = await this.menuService.initContextMenuForWindowWebContents(view.webContents);
view.webContents.on('destroyed', () => {
unregisterContextMenu();
});
} catch (error) {
logger.error(`Initial view.webContents.loadURL("${initialUrl}") failed: ${error.message}, but may retry later`);
}
/**
* Try catch loadUrl, other wise it will throw unhandled promise rejection Error: ERR_CONNECTION_REFUSED (-102) loading 'http://localhost:5212/
* We will set `didFailLoadErrorMessage`, and `didFailLoadTimes < LOAD_VIEW_MAX_RETRIES` in `setupViewEventHandlers`, it will set didFailLoadErrorMessage, and we throw actuarial error after that
*/
const loadInitialUrlWithCatch = async (): Promise<void> => {
try {
await view.webContents.loadURL(initialUrl);
const unregisterContextMenu = await this.menuService.initContextMenuForWindowWebContents(view.webContents);
view.webContents.on('destroyed', () => {
unregisterContextMenu();
});
} catch (error) {
let didFailLoadTimes = 0;
try {
const workspaceMetaData = await this.workspaceService.getMetaData(workspace.id);
didFailLoadTimes = workspaceMetaData.didFailLoadTimes ?? 0;
} catch {}
logger.error(new ViewLoadUrlError(initialUrl, didFailLoadTimes, `${(error as Error).message} ${(error as Error).stack ?? ''}`));
}
};
setupViewEventHandlers(view, browserWindow, {
shouldPauseNotifications: this.shouldPauseNotifications,
workspace,
sharedWebPreferences,
loadInitialUrlWithCatch,
});
await loadInitialUrlWithCatch();
}
public getView = (id: string): BrowserView => this.views[id];

View file

@ -25,7 +25,7 @@ export interface IViewContext {
workspace: IWorkspace;
shouldPauseNotifications: boolean;
sharedWebPreferences: BrowserWindowConstructorOptions['webPreferences'];
initialUrl: string;
loadInitialUrlWithCatch: () => Promise<void>;
}
export interface IViewMeta {
@ -38,7 +38,7 @@ export interface IViewMeta {
export default function setupViewEventHandlers(
view: BrowserView,
browserWindow: BrowserWindow,
{ workspace, sharedWebPreferences, initialUrl }: IViewContext,
{ workspace, sharedWebPreferences, loadInitialUrlWithCatch }: IViewContext,
): void {
// metadata and state about current BrowserView
const viewMeta: IViewMeta = {
@ -128,8 +128,8 @@ export default function setupViewEventHandlers(
await workspaceService.updateMetaData(workspace.id, {
didFailLoadTimes: didFailLoadTimes + 1,
});
await view.webContents.loadURL(initialUrl);
}, 200);
await loadInitialUrlWithCatch();
}, 1000);
return;
}
await workspaceService.updateMetaData(workspace.id, {
@ -143,8 +143,8 @@ export default function setupViewEventHandlers(
}
// edge case to handle failed auth, use setTimeout to prevent infinite loop
if (errorCode === -300 && view.webContents.getURL().length === 0 && workspaceObject.homeUrl.startsWith('http')) {
setTimeout(() => {
void view.webContents.loadURL(getLocalHostUrlWithActualIP(workspaceObject.homeUrl));
setTimeout(async () => {
await loadInitialUrlWithCatch();
}, 1000);
}
});