* 执行操作并处理 429 错误重试 * @param fn 要执行的操作函数 * @param op 操作类型,用于判定该操作在遇到 429 时是否进入指数退避重试 * @returns 操作结果
(fn: () => Promise<T>, op: string)
| 52 | * @returns 操作结果 |
| 53 | */ |
| 54 | private async executeWithRetry<T>(fn: () => Promise<T>, op: string): Promise<T> { |
| 55 | // 最多重试 10 次 |
| 56 | for (let i = 0; i <= 10; i++) { |
| 57 | try { |
| 58 | return await fn(); |
| 59 | } catch (error) { |
| 60 | // 检查错误字符串中是否包含 429 |
| 61 | const errorStr = String(error).toLowerCase(); |
| 62 | if (this.shouldRetry429(op, ` ${errorStr} `) && i < 10) { |
| 63 | // 遇到 429 错误且未达到重试上限,采用指数退避策略延迟后继续重试 |
| 64 | const delay = Math.min(2000 * Math.pow(2, i), 60000); |
| 65 | await new Promise((resolve) => setTimeout(resolve, delay)); |
| 66 | // 继续下一次循环重试 |
| 67 | continue; |
| 68 | } |
| 69 | // 其他错误或达到重试上限,直接抛出 |
| 70 | throw error; |
| 71 | } |
| 72 | } |
| 73 | // 理论上不会到达这里:循环最后一次的 catch 已经把原始错误抛出 |
| 74 | throw new Error(`Max retries exceeded (op=${op})`); |
| 75 | } |
| 76 | |
| 77 | private shouldRetry429(op: string, errorStr: string): boolean { |
| 78 | return ( |