
在现代web应用开发中,与后端api交互是常态。许多异步操作,例如文件处理、数据转换或复杂计算,可能不会立即返回最终结果。api通常会返回一个中间状态(如"pending"、"processing"),然后需要客户端轮询(poll)直至返回最终成功状态(如"done"、"completed")。在这种场景下,简单地发起一次请求是不够的,我们需要一种机制来:
实现条件式重试的核心策略是结合异步编程(async/await)、循环结构和延迟机制。我们将构建一个通用的重试函数,它能够:
下面我们将通过一个具体的 Axios 请求示例,演示如何构建一个健壮的条件式重试函数。
首先,我们需要设置 Axios 请求的基本配置,包括请求方法、URL、头部信息和数据。这里我们使用 qs 库来序列化数据,以适应 application/x-www-form-urlencoded 内容类型。
const axios = require("axios");
const qs = require("qs");
// 假设 apiKey 在当前作用域内可用,请替换为你的实际API密钥
const apiKey = "YOUR_DEEPL_API_KEY";
const initialConfig = {
method: "post",
maxBodyLength: Infinity, // 允许最大请求体长度
url: "https://api-free.deepl.com/v2/document/95BA71197AC66EE4745FF5269CF4399D",
headers: {
Authorization: `DeepL-Auth-Key ${apiKey}`, // DeepL API 密钥通常这样传递
"Content-Type": "application/x-www-form-urlencoded",
},
data: qs.stringify({
document_key: "038A2E0792CE72020E9BB88380D002EB582A6B3AE5883C34DE53C9F17D415D99",
}),
};为了在重试之间引入暂停,我们需要一个简单的 delay 函数。
/**
* 引入延迟的辅助函数
* @param {number} ms - 延迟毫秒数
*/
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));现在,我们将核心逻辑封装在一个 async 函数中,它将处理重试逻辑、状态检查、延迟和错误处理。
/**
* 重试 API 请求直到特定状态或达到最大重试次数
* @param {object} config - Axios 请求配置
* @param {string} targetStatus - 期望的响应状态值
* @param {number} maxRetries - 最大重试次数
* @param {number} initialDelayMs - 初始重试延迟(毫秒)
* @returns {Promise<any>} - 成功时的响应数据
* @throws {Error} - 如果重试失败或达到最大重试次数
*/
async function retryApiRequestUntilStatus(
config,
targetStatus,
maxRetries = 5,
initialDelayMs = 1000
) {
let attempts = 0;
let currentDelay = initialDelayMs; // 当前延迟时间,用于指数退避
while (attempts < maxRetries) {
attempts++;
try {
console.log(`尝试发起请求 (第 ${attempts} 次)...`);
const response = await axios.request(config);
const status = response.data.status;
if (status === targetStatus) {
console.log(`请求成功,状态为 "${targetStatus}"。`);
return response.data; // 返回完整的响应数据
} else {
console.log(`当前状态为 "${status}",不符合预期 "${targetStatus}"。`);
if (attempts < maxRetries) {
console.log(`等待 ${currentDelay / 1000} 秒后重试...`);
await delay(currentDelay);
// 实现指数退避:每次重试失败后增加延迟时间
currentDelay = Math.min(currentDelay * 2, 60000); // 最大延迟不超过60秒
}
}
} catch (error) {
console.error(`请求失败 (第 ${attempts} 次): ${error.message}`);
if (attempts < maxRetries) {
console.log(`等待 ${currentDelay / 1000} 秒后重试...`);
await delay(currentDelay);
currentDelay = Math.min(currentDelay * 2, 60000); // 最大延迟不超过60秒
} else {
// 达到最大重试次数后,抛出错误
throw new Error(`API 请求在 ${maxRetries} 次尝试后仍未成功:${error.message}`);
}
}
}
// 循环结束,但未达到目标状态
throw new Error(`API 请求在 ${maxRetries} 次尝试后仍未达到状态 "${targetStatus}"。`);
}最后,我们可以在一个立即执行的异步函数中调用这个重试逻辑。
// 示例调用
(async () => {
try {
const result = await retryApiRequestUntilStatus(
initialConfig,
"done", // 期望的目标状态
10, // 最大重试次数
500 // 初始延迟 500 毫秒
);
console.log("最终结果:", result);
} catch (error) {
console.error("操作失败:", error.message);
}
})();在实现条件式重试机制时,除了上述代码,还有一些重要的考量和最佳实践:
重试间隔与指数退避:
最大重试次数:
幂等性:
用户体验:
日志记录与监控:
错误分类:
通过本教程,我们学习了如何构建一个健壮的 Axios 条件式重试机制,以应对异步API操作中常见的轮询需求和临时性故障。这种模式不仅提高了应用程序的韧性,确保了数据最终的一致性,同时也通过合理的延迟和重试限制,维护了与API服务之间的良好交互。在实际项目中,根据具体业务场景和API特性,灵活调整重试策略和参数,将是构建高可靠性应用的关键。
以上就是Axios 异步请求的条件式重试与状态检测的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号