js实现轮询
轮询的基本概念
轮询(Polling)是一种客户端定期向服务器发送请求以检查数据更新的技术。适用于需要实时性但无法使用WebSocket或Server-Sent Events(SSE)的场景。
使用 setInterval 实现基础轮询
通过 setInterval 定时发起请求,简单但可能造成资源浪费:

function startPolling(url, interval = 5000) {
const poll = setInterval(async () => {
try {
const response = await fetch(url);
const data = await response.json();
console.log('Polled data:', data);
} catch (error) {
console.error('Polling error:', error);
}
}, interval);
// 返回清除函数以便手动停止
return () => clearInterval(poll);
}
// 使用示例
const stopPolling = startPolling('https://api.example.com/data');
// 停止轮询:stopPolling();
使用 setTimeout 实现递归轮询
更灵活的方案,可根据服务器响应动态调整间隔:

function recursivePolling(url, interval = 5000) {
setTimeout(async () => {
try {
const response = await fetch(url);
const data = await response.json();
console.log('Polled data:', data);
// 根据响应决定下次轮询时间(如服务器返回建议间隔)
const nextInterval = data.nextPollInterval || interval;
recursivePolling(url, nextInterval);
} catch (error) {
console.error('Polling error:', error);
// 错误时重试,可增加退避策略
recursivePolling(url, interval * 2);
}
}, interval);
}
// 启动
recursivePolling('https://api.example.com/data');
带退避策略的轮询
避免频繁失败请求导致资源浪费,常见策略如指数退避:
function pollingWithBackoff(url, initialInterval = 1000, maxInterval = 60000) {
let currentInterval = initialInterval;
const poll = async () => {
try {
const response = await fetch(url);
const data = await response.json();
console.log('Polled data:', data);
// 成功时重置间隔
currentInterval = initialInterval;
} catch (error) {
console.error('Polling error:', error);
// 失败时增加间隔,不超过最大值
currentInterval = Math.min(currentInterval * 2, maxInterval);
} finally {
setTimeout(poll, currentInterval);
}
};
poll();
}
// 启动
pollingWithBackoff('https://api.example.com/data');
终止轮询的条件控制
通过标志位或AbortController实现可控终止:
function controllablePolling(url, interval = 5000) {
let isPolling = true;
const abortController = new AbortController();
const poll = async () => {
if (!isPolling) return;
try {
const response = await fetch(url, {
signal: abortController.signal
});
const data = await response.json();
console.log('Polled data:', data);
} catch (error) {
if (error.name !== 'AbortError') {
console.error('Polling error:', error);
}
} finally {
if (isPolling) {
setTimeout(poll, interval);
}
}
};
poll();
// 提供终止方法
return {
stop: () => {
isPolling = false;
abortController.abort();
}
};
}
// 使用示例
const { stop } = controllablePolling('https://api.example.com/data');
// 停止轮询:stop();
注意事项
- 性能影响:频繁轮询会增加服务器负载,需合理设置间隔。
- 竞态条件:确保请求顺序与响应顺序一致,必要时使用请求ID标记。
- 错误处理:网络波动时需实现重试或退避逻辑。
- 替代方案:优先考虑WebSocket或SSE等长连接技术(若支持)。






