1. 错误检测与捕获
- React 子应用内部:
- 使用
try - catch
:在 React 组件的生命周期函数(如 componentDidMount
、componentDidUpdate
)以及自定义函数中,手动使用 try - catch
块来捕获可能发生的错误。例如:
componentDidMount() {
try {
// 可能出错的代码
this.fetchData();
} catch (error) {
this.handleError(error);
}
}
fetchData() {
// 模拟异步请求
setTimeout(() => {
throw new Error('Network error');
}, 1000);
}
handleError(error) {
// 处理错误,例如记录日志等
console.error('Local error caught:', error);
}
- 错误边界的改进使用:虽然错误边界存在局限性,但仍可在子应用内使用它捕获渲染过程、生命周期方法和构造函数中的错误。创建自定义错误边界组件,例如:
class CustomErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, errorInfo) {
this.setState({ hasError: true });
// 这里可以先进行本地处理,例如记录到本地日志
console.error('Error in component:', error, errorInfo);
// 后续将错误传递给全局处理机制
}
render() {
if (this.state.hasError) {
// 返回友好的错误提示
return <div>An error occurred in this component.</div>;
}
return this.props.children;
}
}
<CustomErrorBoundary>
<MyComponent />
</CustomErrorBoundary>
- 微前端框架层面:
- 监听
window.onerror
:在微前端的主框架中,可以监听 window.onerror
事件来捕获未被 React 错误边界捕获的全局 JavaScript 错误。例如:
window.onerror = function (message, source, lineno, colno, error) {
// 处理全局错误,例如上报到服务器
console.error('Global error caught:', message, source, lineno, colno, error);
// 这里可以调用全局错误处理函数进行统一处理
globalErrorHandler({ message, source, lineno, colno, error });
return true; // 阻止默认的错误处理行为
};
- 监听
unhandledrejection
:对于 Promise 拒绝但未被处理的情况,监听 unhandledrejection
事件,在微前端主框架中添加如下代码:
window.addEventListener('unhandledrejection', function (event) {
console.error('Unhandled promise rejection:', event.reason);
// 调用全局错误处理函数
globalErrorHandler({ error: event.reason, type: 'unhandledrejection' });
});
2. 错误上报
- 自定义上报函数:创建一个全局的错误上报函数,例如
sendErrorToServer
,在捕获到错误后调用它。
function sendErrorToServer(errorData) {
const { message, source, lineno, colno, error, type } = errorData;
const data = {
message,
source,
lineno,
colno,
errorStack: error? error.stack : '',
type
};
// 使用 fetch 或者 XMLHttpRequest 将数据发送到服务器
fetch('/api/error', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
}
- 整合到错误处理流程:在上述
try - catch
、错误边界的 componentDidCatch
以及 window.onerror
和 unhandledrejection
的处理函数中调用 sendErrorToServer
函数。例如在 window.onerror
中:
window.onerror = function (message, source, lineno, colno, error) {
sendErrorToServer({ message, source, lineno, colno, error });
return true;
};
3. 错误处理
- 全局错误处理函数:创建一个全局错误处理函数
globalErrorHandler
,用于统一处理各个子应用捕获并上报的错误。
function globalErrorHandler(errorData) {
// 记录到日志文件(可以是本地日志或者服务器端日志)
console.error('Global error handling:', errorData);
// 可以根据错误类型进行不同的处理
if (errorData.type === 'unhandledrejection') {
// 针对未处理的 Promise 拒绝错误的特殊处理
console.warn('Special handling for unhandled promise rejection');
}
// 调用错误上报函数
sendErrorToServer(errorData);
}
- 用户反馈:在捕获到错误后,除了上报和记录日志,还可以给用户提供友好的反馈。例如,在 React 应用中,可以通过状态管理工具(如 Redux)来控制显示一个全局的错误提示框。
- 定义 Redux action 和 reducer:
// actions.js
const SET_GLOBAL_ERROR ='SET_GLOBAL_ERROR';
export const setGlobalError = (error) => ({
type: SET_GLOBAL_ERROR,
payload: error
});
// reducer.js
const initialState = {
globalError: null
};
const errorReducer = (state = initialState, action) => {
switch (action.type) {
case SET_GLOBAL_ERROR:
return {
...state,
globalError: action.payload
};
default:
return state;
}
};
- 在错误处理时触发 action:在
globalErrorHandler
中触发 setGlobalError
action:
import { setGlobalError } from './actions';
import store from './store';
function globalErrorHandler(errorData) {
// 记录日志和上报错误
console.error('Global error handling:', errorData);
sendErrorToServer(errorData);
// 设置全局错误状态
store.dispatch(setGlobalError(errorData));
}
- 在组件中显示错误提示:在 React 组件中订阅 Redux 状态,显示错误提示。
import React from'react';
import { useSelector } from'react-redux';
const ErrorNotification = () => {
const globalError = useSelector(state => state.globalError);
if (!globalError) return null;
return (
<div className="error-notification">
<p>{globalError.message}</p>
</div>
);
};
export default ErrorNotification;
- 将
ErrorNotification
组件添加到应用的布局中:
import React from'react';
import ErrorNotification from './ErrorNotification';
const App = () => {
return (
<div>
<ErrorNotification />
{/* 其他应用内容 */}
</div>
);
};
export default App;