async/await轮询核心是while循环+await请求,需设终止条件(如状态达标)、兜底机制(超时、最大重试次数);示例中flexiblePoll支持自定义isSuccess、shouldRetry、interval等参数,提升复用性。

用 async/await 实现轮询,核心是用 while 循环 + await 等待每次请求,并设置终止条件和安全兜底(如超时、最大重试次数)。
基础轮询结构:等待响应并判断结果
每次请求后检查返回值是否符合预期,满足则跳出循环,否则等待一段时间再试:
async function pollUntilSuccess(url, options = {}, { interval = 1000, maxAttempts = 10 } = {}) {
let attempt = 0;
while (attempt < maxAttempts) {
try {
const res = await fetch(url, options);
const data = await res.json();
<pre class="brush:php;toolbar:false;"> // ✅ 自定义成功条件,例如 status === 'done' 或 data.result === true
if (data.status === 'done') {
return data; // 轮询成功,返回结果
}
} catch (err) {
console.warn(`第 ${attempt + 1} 次请求失败:`, err.message);
}
attempt++;
if (attempt < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, interval));
}}
throw new Error(轮询失败:已尝试 ${maxAttempts} 次,仍未获取到有效结果);
}
加入超时控制:避免无限等待
仅靠重试次数不够,网络卡顿可能导致单次请求耗时过长。建议给每次 fetch 加上 timeout:
- 用
AbortController控制单次请求超时(如 5 秒) - 超时后捕获
AbortError,不中断整个轮询,继续下一次 - 示例中将单次请求限制为 5000ms,轮询间隔仍为 1000ms
async function pollWithTimeout(url, { timeout = 5000, ...fetchOptions } = {}, config = {}) {
const { interval = 1000, maxAttempts = 10 } = config;
let attempt = 0;
<p>while (attempt < maxAttempts) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);</p><pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;">try {
const res = await fetch(url, {
...fetchOptions,
signal: controller.signal
});
clearTimeout(timeoutId);
const data = await res.json();
if (data.status === 'done') {
return data;
}
} catch (err) {
if (err.name === 'AbortError') {
console.warn(`第 ${attempt + 1} 次请求超时(>${timeout}ms)`);
} else {
console.warn(`第 ${attempt + 1} 次请求异常:`, err.message);
}
}
attempt++;
if (attempt < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, interval));
}}
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
throw new Error('轮询超时或达到最大重试次数'); }
支持自定义成功判断与错误处理逻辑
把「什么算成功」和「什么该重试」抽成函数,提升复用性和可读性:
-
isSuccess(data):返回true表示轮询可结束 -
shouldRetry(error):决定是否因当前错误继续轮询(例如跳过 404,但不跳过 500) - 便于对接不同接口规范(如有的用
code === 0,有的用finished: true)
async function flexiblePoll(url, fetchOptions, {
isSuccess = data => data?.status === 'done',
shouldRetry = () => true,
interval = 1000,
maxAttempts = 10,
timeout = 5000
} = {}) {
let attempt = 0;
while (attempt < maxAttempts) {
const controller = new AbortController();
setTimeout(() => controller.abort(), timeout);
<pre class="brush:php;toolbar:false;">try {
const res = await fetch(url, { ...fetchOptions, signal: controller.signal });
const data = await res.json();
if (isSuccess(data)) {
return data;
}
// 非成功但未满足终止条件,继续轮询
if (attempt < maxAttempts - 1) {
await new Promise(r => setTimeout(r, interval));
}
} catch (err) {
if (shouldRetry(err)) {
if (attempt < maxAttempts - 1) {
await new Promise(r => setTimeout(r, interval));
}
} else {
throw err;
}
}
attempt++;} throw new Error('轮询终止:未满足成功条件且无更多重试机会'); }
实际调用示例
假设后端有个任务接口 /api/task/123,返回:
{ "id": 123, "status": "processing" } → 继续轮询<br>{ "id": 123, "status": "done", "result": "success!" } → 成功退出你可以这样使用:
try {
const result = await flexiblePoll('/api/task/123', {}, {
isSuccess: data => data?.status === 'done',
interval: 2000,
maxAttempts: 15
});
console.log('任务完成:', result.result);
} catch (err) {
console.error('轮询失败:', err.message);
}不复杂但容易忽略细节:加超时、设上限、明确定义成功、区分错误类型。写好一次,多个场景都能复用。

















