javascript中用柯里化实现请求超时自动重试,核心是分层固化“请求函数”“超时时间”“重试次数”“重试间隔”等参数,先通过abortcontroller控制超时、递归+settimeout实现重试,再用柯里化封装为可配置策略工厂,支持自定义重试条件与多场景复用。

JavaScript 中用柯里化实现请求超时自动重试,核心是把“请求函数”“超时时间”“重试次数”“重试间隔”等参数分层固化,让每次调用更灵活、复用性更强。不是直接写一个 retry(fetch, 5000, 3),而是先 curry 化,再按需配置。
1. 先写一个基础的带超时和重试的 fetch 封装
不依赖柯里化也能做,但它是后续柯里化的基础:
- 用 AbortController 控制单次请求超时
- 用 递归 + setTimeout 实现指数退避或固定间隔重试
- 错误类型要区分:网络失败、超时、4xx/5xx 状态码(通常只对前两者重试)
示例(不带柯里化):
const requestWithRetry = async (url, options = {}, maxRetries = 2, timeout = 8000, delay = 1000) => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
<p>try {
const res = await fetch(url, { ...options, signal: controller.signal });
clearTimeout(timeoutId);
if (!res.ok) throw new Error(<code>HTTP ${res.status}</code>);
return res;
} catch (err) {
clearTimeout(timeoutId);
if (maxRetries setTimeout(r, delay));
return requestWithRetry(url, options, maxRetries - 1, timeout, delay);
}
};</p>2. 用柯里化把参数逐层固化
柯里化让函数变成可配置的“工厂”:先定策略(超时/重试),再定目标(url/options)。
- 第一层:接收 maxRetries、timeout、delay,返回一个“重试策略函数”
- 第二层:接收 url 和 options,返回一个可执行的 Promise
- 这样就能写出
const apiGet = withRetry(3, 10000, 500),再apiGet('/user')
柯里化实现(简洁版):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const withRetry = (maxRetries, timeout = 8000, delay = 1000) =>
(url, options = {}) =>
requestWithRetry(url, options, maxRetries, timeout, delay);
3. 支持更灵活的重试条件(如仅重试特定状态码)
柯里化也方便扩展判断逻辑。比如加一个 shouldRetry 函数:
- 把它作为柯里化第一层的可选参数,返回增强版策略函数
- 默认重试网络错误和超时;传入自定义函数后,可支持
res.status === 429或err?.code === 'ECONNREFUSED'
增强版柯里化:
const withRetry = (maxRetries, timeout = 8000, delay = 1000, shouldRetry = (err) =>
err.name === 'AbortError' || err.name === 'TypeError') =>
(url, options = {}) => {
const attempt = async (retriesLeft) => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const res = await fetch(url, { ...options, signal: controller.signal });
clearTimeout(timeoutId);
if (!res.ok && !shouldRetry(new Error(`HTTP ${res.status}`))) {
throw new Error(`HTTP ${res.status}`);
}
return res;
} catch (err) {
clearTimeout(timeoutId);
if (retriesLeft setTimeout(r, delay));
return attempt(retriesLeft - 1);
}
};
return attempt(maxRetries);
};
4. 实际使用场景举例
柯里化后,不同接口可以复用同一套策略,又互不干扰:
-
const getUser = withRetry(3, 5000, 300)((url) => fetch(url))→ 简单 GET -
const postOrder = withRetry(2, 12000, 800, (e) => e?.status === 429)→ 只对限流重试 -
const uploadFile = withRetry(1, 30000, 2000)→ 大文件上传,超时长、只试一次
不复杂但容易忽略:柯里化本身不解决异步,它只是组织参数的方式;真正健壮的重试还要考虑取消重复请求、避免无限 pending、记录重试日志等,这些可在封装层叠加。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










