设计思路
- 错误处理机制设计
- 网络异常:使用
window.navigator.onLine
属性判断网络状态,在发起请求前进行检查。如果网络离线,直接抛出一个特定的网络异常错误。在请求过程中,如果发生网络错误(如fetch
的type
为'network'
),捕获并处理该错误。
- 请求超时:在
fetch
请求时设置signal
,通过AbortController
实现超时控制。当超时时,终止请求并抛出超时错误。
- API接口变更:在请求返回时,检查返回的状态码和数据结构。如果状态码不符合预期(如非200 - 299),或者数据结构与预期不符,抛出相应的错误。可以通过定义一套规范的错误码和错误信息,方便统一处理。
- 增加新处理逻辑且不影响现有业务逻辑
- 采用装饰器模式:在高阶组件的基础上,使用装饰器函数来添加新的处理逻辑。这样可以将新的处理逻辑与原有的高阶组件逻辑解耦。每个装饰器负责处理一种特定的边界情况,如网络异常处理装饰器、请求超时处理装饰器等。
- 配置化管理:将处理逻辑相关的配置(如超时时间、错误码映射等)提取到一个配置文件中,方便统一管理和修改。在高阶组件或装饰器中读取这些配置,以实现不同环境下的灵活配置。
关键代码示例
- 网络异常处理
// 检查网络状态的函数
function checkNetworkStatus() {
if (!window.navigator.onLine) {
throw new Error('Network is offline');
}
}
// 网络异常处理装饰器
function withNetworkErrorHandling(WrappedComponent) {
return function (props) {
try {
checkNetworkStatus();
} catch (error) {
// 处理网络异常,比如显示提示信息等
console.error('Network error:', error.message);
return null;
}
return <WrappedComponent {...props} />;
};
}
- 请求超时处理
// 请求超时处理装饰器
function withTimeoutHandling(WrappedComponent, timeout = 5000) {
return function (props) {
const controller = new AbortController();
const { signal } = controller;
const timeoutId = setTimeout(() => {
controller.abort();
}, timeout);
// 模拟API请求,这里用fetch举例
const fetchData = async () => {
try {
const response = await fetch('your-api-url', { signal });
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
return data;
} catch (error) {
if (error.name === 'AbortError') {
console.error('Request timed out');
} else {
console.error('Fetch error:', error.message);
}
return null;
}
};
// 在组件卸载时清除定时器
useEffect(() => {
return () => {
clearTimeout(timeoutId);
};
}, []);
// 调用API并传递数据给WrappedComponent
const data = fetchData();
return <WrappedComponent data={data} {...props} />;
};
}
- 结合高阶组件使用示例
// 假设这是原有的高阶组件封装的API请求
function withAPIFetch(WrappedComponent, apiUrl) {
return function (props) {
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error('Network response was not ok');
}
const result = await response.json();
setData(result);
} catch (error) {
console.error('API fetch error:', error.message);
}
};
fetchData();
}, [apiUrl]);
return <WrappedComponent data={data} {...props} />;
};
}
// 使用装饰器和高阶组件
const MyComponent = ({ data }) => {
return (
<div>
{data? <p>{JSON.stringify(data)}</p> : <p>Loading...</p>}
</div>
);
};
const EnhancedComponent = withNetworkErrorHandling(withTimeoutHandling(withAPIFetch(MyComponent, 'your-api-url'), 3000));