Promise本身无超时机制,需用Promise.race结合定时reject的Promise实现;封装fetchWithTimeout函数,利用AbortController中断请求并清理定时器;业务中需区分超时与网络错误,配合UI状态提升体验。

Promise 本身不内置超时机制,但可以通过 Promise.race 结合一个延迟 reject 的 Promise 来实现加载超时提示。
用 Promise.race 实现超时控制
核心思路:把目标请求 Promise 和一个“定时失败”的 Promise 一起传给 Promise.race(),谁先完成(fulfilled 或 rejected)就采用谁的结果。
- 正常请求较快完成 → 返回数据,超时 Promise 被忽略
- 请求卡住或太慢 → 超时 Promise 先 reject,触发错误处理并显示提示
封装一个带超时的 fetch 请求
以 fetch 为例,可封装成可复用函数:
function fetchWithTimeout(url, options = {}, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
return Promise.race([
fetch(url, { ...options, signal: controller.signal })
.finally(() => clearTimeout(timeoutId)),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('请求超时')), timeout)
)
]);
}
注意:AbortController 可中断 fetch,避免资源浪费;finally 清理定时器防止内存泄漏。
立即学习“Java免费学习笔记(深入)”;
在业务中使用并提示用户
调用时捕获错误,区分网络错误和超时场景:
fetchWithTimeout('/api/data', {}, 3000)
.then(res => res.json())
.then(data => console.log('成功:', data))
.catch(err => {
if (err.message === '请求超时') {
alert('加载太慢了,请检查网络或稍后重试');
// 或更新 UI:显示「加载超时」按钮、重试入口等
} else {
alert('请求失败,请重试');
}
});
更健壮的提示体验建议
单纯 alert 不友好,推荐结合 UI 状态管理:
- 请求开始时显示「加载中…」,禁用操作按钮
- 超时时替换为「加载超时」状态,并提供「重试」按钮
- 可加简单倒计时文案(如“正在加载… 2s”),提升感知
- 对关键接口,超时后自动重试一次(需防重复提交)


















