improve: handle unhandled exception
This commit is contained in:
parent
a8a392b20d
commit
7200896940
11
client/demo/dist/index.html
vendored
11
client/demo/dist/index.html
vendored
@ -1,10 +1 @@
|
||||
<!DOCTYPE html>
|
||||
<html style="width: 100%; height: 100%; overflow: hidden">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Voice Changer Client Demo</title>
|
||||
<script defer src="index.js"></script></head>
|
||||
<body style="width: 100%; height: 100%; margin: 0px">
|
||||
<div id="app" style="width: 100%; height: 100%"></div>
|
||||
</body>
|
||||
</html>
|
||||
<!doctype html><html style="width:100%;height:100%;overflow:hidden"><head><meta charset="utf-8"/><title>Voice Changer Client Demo</title><script defer="defer" src="index.js"></script></head><body style="width:100%;height:100%;margin:0"><div id="app" style="width:100%;height:100%"></div></body></html>
|
1147
client/demo/dist/index.js
vendored
1147
client/demo/dist/index.js
vendored
File diff suppressed because one or more lines are too long
31
client/demo/dist/index.js.LICENSE.txt
vendored
Normal file
31
client/demo/dist/index.js.LICENSE.txt
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
@ -4,9 +4,9 @@ import { library } from "@fortawesome/fontawesome-svg-core";
|
||||
import { fas } from "@fortawesome/free-solid-svg-icons";
|
||||
import { far } from "@fortawesome/free-regular-svg-icons";
|
||||
import { fab } from "@fortawesome/free-brands-svg-icons";
|
||||
import { ErrorInfo, useEffect, useMemo, useState, } from "react";
|
||||
import { ErrorInfo, useEffect, useMemo, useState } from "react";
|
||||
|
||||
import "./css/App.css"
|
||||
import "./css/App.css";
|
||||
import ErrorBoundary from "./001_provider/900_ErrorBoundary";
|
||||
import { AppStateProvider } from "./001_provider/001_AppStateProvider";
|
||||
import { AppRootProvider, useAppRoot } from "./001_provider/001_AppRootProvider";
|
||||
@ -16,102 +16,108 @@ import { useMessageBuilder } from "./hooks/useMessageBuilder";
|
||||
|
||||
library.add(fas, far, fab);
|
||||
|
||||
|
||||
const container = document.getElementById("app")!;
|
||||
const root = createRoot(container);
|
||||
|
||||
const App = () => {
|
||||
const { appGuiSettingState } = useAppRoot()
|
||||
const { appGuiSettingState } = useAppRoot();
|
||||
const front = useMemo(() => {
|
||||
if (appGuiSettingState.appGuiSetting.type == "demo") {
|
||||
return <Demo></Demo>
|
||||
return <Demo></Demo>;
|
||||
} else {
|
||||
return <>unknown gui type. {appGuiSettingState.appGuiSetting.type}</>
|
||||
return <>unknown gui type. {appGuiSettingState.appGuiSetting.type}</>;
|
||||
}
|
||||
}, [appGuiSettingState.appGuiSetting.type])
|
||||
}, [appGuiSettingState.appGuiSetting.type]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{front}
|
||||
</>
|
||||
)
|
||||
}
|
||||
return <>{front}</>;
|
||||
};
|
||||
|
||||
const AppStateWrapper = () => {
|
||||
const { appGuiSettingState, getGUISetting } = useAppRoot()
|
||||
const messageBuilderState = useMessageBuilder()
|
||||
const { appGuiSettingState, getGUISetting } = useAppRoot();
|
||||
const messageBuilderState = useMessageBuilder();
|
||||
// エラーメッセージ登録
|
||||
useMemo(() => {
|
||||
messageBuilderState.setMessage(__filename, "Problem", { "ja": "ちょっと問題が起きたみたいです。", "en": "Looks like there's a bit of a problem." })
|
||||
messageBuilderState.setMessage(__filename, "Problem-sub1", { "ja": "このアプリで管理している情報をクリアすると回復する場合があります。", "en": "" })
|
||||
messageBuilderState.setMessage(__filename, "Problem-sub2", { "ja": "下記のボタンを押して情報をクリアします。", "en": "If you clear the information being managed by this app, it may be recoverable." })
|
||||
messageBuilderState.setMessage(__filename, "Problem-action1", { "ja": "アプリを初期化", "en": "Initialize" })
|
||||
messageBuilderState.setMessage(__filename, "Problem-action2", { "ja": "初期化せずリロード", "en": "Reload without initialize" })
|
||||
}, [])
|
||||
messageBuilderState.setMessage(__filename, "Problem", { ja: "ちょっと問題が起きたみたいです。", en: "Looks like there's a bit of a problem." });
|
||||
messageBuilderState.setMessage(__filename, "Problem-sub1", { ja: "このアプリで管理している情報をクリアすると回復する場合があります。", en: "" });
|
||||
messageBuilderState.setMessage(__filename, "Problem-sub2", { ja: "下記のボタンを押して情報をクリアします。", en: "If you clear the information being managed by this app, it may be recoverable." });
|
||||
messageBuilderState.setMessage(__filename, "Problem-action1", { ja: "アプリを初期化", en: "Initialize" });
|
||||
messageBuilderState.setMessage(__filename, "Problem-action2", { ja: "初期化せずリロード", en: "Reload without initialize" });
|
||||
}, []);
|
||||
|
||||
// エラーバウンダリー設定
|
||||
const [error, setError] = useState<{ error: Error, errorInfo: ErrorInfo }>()
|
||||
const { removeDB } = useIndexedDB({ clientType: null })
|
||||
|
||||
const [error, setError] = useState<{ error: Error; errorInfo: ErrorInfo | null; reason: any }>();
|
||||
const { removeDB } = useIndexedDB({ clientType: null });
|
||||
|
||||
const errorComponent = useMemo(() => {
|
||||
const errorName = error?.error.name || "no error name"
|
||||
const errorMessage = error?.error.message || "no error message"
|
||||
const errorInfos = (error?.errorInfo.componentStack || "no error stack").split("\n")
|
||||
const errorName = error?.error.name || "no error name";
|
||||
const errorMessage = error?.error.message || "no error message";
|
||||
const errorInfos = (error?.errorInfo?.componentStack || "no error stack").split("\n");
|
||||
const reasonMessage = (error?.reason || "no reason").toString();
|
||||
const reasonStack = (error?.reason.stack || "no stack").split("\n") as string[];
|
||||
|
||||
const onClearCacheClicked = async () => {
|
||||
await removeDB()
|
||||
await removeDB();
|
||||
location.reload();
|
||||
}
|
||||
};
|
||||
const onReloadClicked = () => {
|
||||
location.reload();
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="error-container">
|
||||
<div className="top-error-message">
|
||||
{messageBuilderState.getMessage(__filename, "Problem")}
|
||||
</div>
|
||||
<div className="top-error-message">{messageBuilderState.getMessage(__filename, "Problem")}</div>
|
||||
<div className="top-error-description">
|
||||
<p> {messageBuilderState.getMessage(__filename, "Problem-sub1")}</p>
|
||||
<p> {messageBuilderState.getMessage(__filename, "Problem-sub2")}</p>
|
||||
<p><button onClick={onClearCacheClicked}>{messageBuilderState.getMessage(__filename, "Problem-action1")}</button></p>
|
||||
<p><button onClick={onReloadClicked}>{messageBuilderState.getMessage(__filename, "Problem-action2")}</button></p>
|
||||
<p>
|
||||
<button onClick={onClearCacheClicked}>{messageBuilderState.getMessage(__filename, "Problem-action1")}</button>
|
||||
</p>
|
||||
<p>
|
||||
<button onClick={onReloadClicked}>{messageBuilderState.getMessage(__filename, "Problem-action2")}</button>
|
||||
</p>
|
||||
</div>
|
||||
<div className="error-detail">
|
||||
<div className="error-name">
|
||||
{errorName}
|
||||
</div>
|
||||
<div className="error-message">
|
||||
{errorMessage}
|
||||
</div>
|
||||
<div className="error-name">{errorName}</div>
|
||||
<div className="error-message">{errorMessage}</div>
|
||||
<div className="error-info-container">
|
||||
{errorInfos.map(x => {
|
||||
return <div className="error-info-line" key={x}>{x}</div>
|
||||
{errorInfos.map((x) => {
|
||||
return (
|
||||
<div className="error-info-line" key={x}>
|
||||
{x}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className="error-detail">
|
||||
<div className="error-name">{reasonMessage}</div>
|
||||
<div className="error-message"></div>
|
||||
<div className="error-info-container">
|
||||
{reasonStack.map((x) => {
|
||||
return (
|
||||
<div className="error-info-line" key={x}>
|
||||
{x}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [error])
|
||||
|
||||
const updateError = (error: Error, errorInfo: React.ErrorInfo) => {
|
||||
console.log("error compo", error, errorInfo)
|
||||
setError({ error, errorInfo })
|
||||
}
|
||||
);
|
||||
}, [error]);
|
||||
|
||||
const updateError = (error: Error, errorInfo: React.ErrorInfo | null, reason: any) => {
|
||||
setError({ error, errorInfo, reason });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const loadDefaultModelType = async () => {
|
||||
getGUISetting()
|
||||
}
|
||||
loadDefaultModelType()
|
||||
}, [])
|
||||
|
||||
|
||||
getGUISetting();
|
||||
};
|
||||
loadDefaultModelType();
|
||||
}, []);
|
||||
|
||||
if (!appGuiSettingState.guiSettingLoaded) {
|
||||
return <>loading...</>
|
||||
return <>loading...</>;
|
||||
} else {
|
||||
return (
|
||||
<ErrorBoundary fallback={errorComponent} onError={updateError}>
|
||||
@ -119,14 +125,12 @@ const AppStateWrapper = () => {
|
||||
<App></App>
|
||||
</AppStateProvider>
|
||||
</ErrorBoundary>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
root.render(
|
||||
<AppRootProvider>
|
||||
<AppStateWrapper></AppStateWrapper>
|
||||
</AppRootProvider>
|
||||
</AppRootProvider>,
|
||||
);
|
||||
|
||||
|
@ -1,17 +1,17 @@
|
||||
import React, { ErrorInfo } from 'react';
|
||||
import React, { ErrorInfo } from "react";
|
||||
|
||||
type ErrorBoundaryProps = {
|
||||
children: React.ReactNode;
|
||||
fallback: React.ReactNode;
|
||||
onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
|
||||
}
|
||||
onError: (error: Error, errorInfo: React.ErrorInfo | null, reason: any) => void;
|
||||
};
|
||||
|
||||
type ErrorBoundaryState = {
|
||||
hasError: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
private eventHandler: () => void
|
||||
private eventHandler: () => void;
|
||||
constructor(props: ErrorBoundaryProps) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
@ -24,24 +24,31 @@ class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundarySta
|
||||
}
|
||||
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||
// For logging
|
||||
console.warn("React Error Boundary Catch", error, errorInfo)
|
||||
console.warn("React Error Boundary Catch", error, errorInfo);
|
||||
const { onError } = this.props;
|
||||
if (onError) {
|
||||
onError(error, errorInfo);
|
||||
onError(error, errorInfo, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 非同期例外対応
|
||||
updateError() {
|
||||
this.setState({ hasError: true });
|
||||
}
|
||||
handledRejection = (event: PromiseRejectionEvent) => {
|
||||
const { onError } = this.props;
|
||||
const error = new Error(event.type);
|
||||
onError(error, null, event.reason);
|
||||
this.setState({ hasError: true });
|
||||
};
|
||||
componentDidMount() {
|
||||
window.addEventListener('unhandledrejection', this.eventHandler)
|
||||
// window.addEventListener('unhandledrejection', this.eventHandler)
|
||||
window.addEventListener("unhandledrejection", this.handledRejection);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('unhandledrejection', this.eventHandler)
|
||||
// window.removeEventListener('unhandledrejection', this.eventHandler)
|
||||
window.removeEventListener("unhandledrejection", this.handledRejection);
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -52,5 +59,4 @@ class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundarySta
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default ErrorBoundary;
|
||||
export default ErrorBoundary;
|
||||
|
Loading…
x
Reference in New Issue
Block a user