Js轮训实现
轮询(Polling)的实现方法
轮询是一种客户端定期向服务器发送请求以获取最新数据的技术。以下是几种常见的实现方式:
使用 setInterval 实现基础轮询
function startPolling(url, interval) {
const poll = setInterval(async () => {
try {
const response = await fetch(url);
const data = await response.json();
console.log('Polling data:', data);
} catch (error) {
console.error('Polling error:', error);
}
}, interval);
// 返回停止函数
return () => clearInterval(poll);
}
// 使用示例
const stopPolling = startPolling('/api/data', 5000);
// 需要停止时调用
// stopPolling();
带有错误处理和退避策略的轮询
async function advancedPolling(url, interval, maxRetries = 3) {
let retryCount = 0;
const poll = async () => {
try {
const response = await fetch(url);
if (!response.ok) throw new Error('Network response was not ok');
const data = await response.json();
console.log('Polling data:', data);
retryCount = 0; // 重置重试计数器
} catch (error) {
console.error('Polling error:', error);
retryCount++;
if (retryCount >= maxRetries) {
console.error('Max retries reached, stopping polling');
return;
}
// 指数退避
const backoffDelay = Math.min(interval * (2 retryCount), 30000);
setTimeout(poll, backoffDelay);
return;
}
setTimeout(poll, interval);
};
poll();
}
// 使用示例
advancedPolling('/api/data', 5000);
基于 Promise 的轮询实现
function promisePolling(fetcher, interval, condition) {
const check = async () => {
try {
const result = await fetcher();
if (condition(result)) {
return result;
}
} catch (error) {
console.error('Polling error:', error);
}
return new Promise(resolve => {
setTimeout(() => resolve(check()), interval);
});
};
return check();
}
// 使用示例
promisePolling(
() => fetch('/api/data').then(res => res.json()),
2000,
data => data.status === 'ready'
).then(finalData => {
console.log('Final data:', finalData);
});
使用 AbortController 实现可取消的轮询
function cancellablePolling(url, interval) {
const controller = new AbortController();
const poll = async () => {
try {
const response = await fetch(url, {
signal: controller.signal
});
const data = await response.json();
console.log('Polling data:', data);
if (!controller.signal.aborted) {
setTimeout(poll, interval);
}
} catch (error) {
if (error.name !== 'AbortError') {
console.error('Polling error:', error);
setTimeout(poll, interval);
}
}
};
poll();
return () => controller.abort();
}
// 使用示例
const stopPolling = cancellablePolling('/api/data', 3000);
// 需要停止时调用
// stopPolling();
轮询的最佳实践
-
设置合理的间隔时间:根据应用需求平衡实时性和服务器负载,通常1-10秒不等。
-
实现退避机制:在错误发生时逐步增加轮询间隔,避免网络问题时的请求风暴。
-
添加取消功能:页面切换或组件卸载时停止轮询,防止内存泄漏。
-
错误处理:妥善处理网络错误和服务器错误,考虑最大重试次数。
-
考虑使用更高效的技术:对于需要更高实时性的场景,可以考虑WebSocket或Server-Sent Events(SSE)。
轮询的替代方案
-
WebSocket:提供全双工通信通道,适合高频率数据更新场景。
-
Server-Sent Events (SSE):服务器可以向客户端推送更新,适合单向数据流。
-
长轮询:服务器在有数据时才响应,减少无效请求。

选择哪种技术取决于具体应用场景、实时性要求和服务器资源限制。





