在开发中,很多小伙伴可能会遇到不少的情况,那就是请求服务器的时候,因为网络问题或者其他别的导致请求失败,如何处理。
- 举一个最简单的业务场景就是:当项目中部署了性能监控,当监控的请求数量达到自定义的阈值时,要求发送数据给后端,如果此时存在发送失败,如何实现重发?
实现方案
- 借用第三方库实现
- 自定义retry
1.借用第三方库实现
1. 使用 retry 库
安装 npm install retry || yarn add retry
使用:
import retry from 'retry';
export async function getServerSideProps() {
const operation = retry.operation({
retries: 3, // 重试次数
factor: 2, // 指数退避的增长因子
minTimeout: 1000, // 初始等待时间
maxTimeout: 5000, // 最大等待时间
});
return new Promise((resolve, reject) => {
operation.attempt(async (currentAttempt) => {
try {
const res = await fetch('https://api.example.com/');
if (res.code === 失败) throw new Error('请求失败');
resolve({ data: { res } });
} catch (error) {
if (operation.retry(error)) {
console.log(`Attempt ${currentAttempt} failed. Retrying...`);
return;
}
reject(error); // 超过重试次数后抛出错误
}
});
});
}
function Page({ data }) {
return (
<div>
<h1>{data.title}</h1>
<p>{data.content}</p>
</div>
);
}
export default Page;
2. 使用 axios-retry库
如果使用使用 axios 进行 HTTP 请求,可以使用 axios-retry 库来实现重试逻辑。
安装:npm install axios axios-retry || yarn add axios axios-retry
使用案例 1.配置 Axios 实例
import axios from 'axios';
import { retry } from 'axios-retry';
// 创建 Axios 实例
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
});
// 使用 axios-retry 配置重试策略
retry(instance, {
retries: 3, // 尝试重试的最大次数
retryDelay: (retryCount) => {
// 根据重试次数计算延迟时间
return retryCount * 1000; // 比如第一次重试等待1秒,第二次2秒...
},
shouldResetTimeout: true, // 每次重试是否重新设置超时时间
retryCondition: (error) => {
// 自定义条件判断是否应该重试
const { response, config } = error;
// 如果服务器返回 404,则不再重试
if (response && response.status === 404) return false;
// 其他情况默认重试
return true;
}
});
export default instance;
2. 使用 Axios 实例发起请求
import api from './api'; // 引入上面配置的 Axios 实例
api.get('/some-endpoint')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('请求失败:', error);
});
以上就是axios-retry 简单案例,可以根据自己的业务需求进行配置
2.自定义retry
async function fetchWithRetry(url, options = {}, retries = 3, delay = 1000) {
try {
const res = await fetch(url, options);
if (!res.ok) throw new Error('请求失败');
return res;
} catch (error) {
if (retries > 0) {
console.log(`剩余发送次数${retries}`);
await new Promise((resolve) => setTimeout(resolve, delay));
return fetchWithRetry(url, options, retries - 1, delay * 2); // 指数退避
} else {
throw error; // 超过重试次数后抛出错误
}
}
}
export async function getServerSideProps() {
try {
const data = await fetchWithRetry('https://api.example.com/');
return { props: { data } };
} catch (error) {
return {
props: {
error: 'Failed to fetch data',
},
};
}
}
function Page({ data, error }) {
if (error) {
return <div>Error: {error}</div>;
}
return (
<div>
<h1>{data.title}</h1>
<p>{data.content}</p>
</div>
);
}
export default Page;