打开浏览器开发者工具,轮询切到 Network 面板,轮询盯着那个每隔两秒就跳出来的轮询请求——这就是 Ajax 轮询最直白的模样。客户端像打卡一样,轮询定时朝服务器喊一嗓子:“有新东西没?轮询”服务器回一句“没有”或者“有,给你”,轮询然后连接关闭,轮询过一会儿再来一遍。轮询简单,轮询粗暴,轮询但确实能跑。轮询
我最早接触轮询是轮询在一个内部工单系统里。需求很朴素:用户提交工单后,轮询页面得显示处理状态。轮询后端没搞 WebSocket,轮询也没上 SSE,就丢给我一个接口,让我每 3 秒查一次。我照做了,代码不到十行,
setInterval包一个fetch或者XMLHttpRequest,完事。上线后功能正常,没人抱怨。但打开服务器日志一看,每个用户每分钟产生 20 个请求,其中 19 个返回空数组。那些空数组就是轮询的代价。轮询分两种。短轮询就是上面说的,每次请求立刻返回,不管有没有数据。长轮询稍微聪明点:客户端发请求,服务器先不急着回,把连接挂起,等真有数据了或者超时了再响应。客户端收到响应后立刻再发一个请求,循环往复。长轮询省掉了大量空请求,但服务器要维持一堆挂起的连接,对并发能力是个考验。Node.js 配 EventEmitter 做长轮询挺顺手,PHP 那种一个请求一个进程的模型就有点吃力。
为什么不用 WebSocket?很多时候不是不想,是不能。老项目跑在 IE 上,或者公司网关把 Upgrade 头掐了,再或者后端团队根本排不出工期。轮询的好处是兼容性无敌——只要 HTTP 还在,它就能活。坏处也明显:实时性取决于轮询间隔,间隔长了消息延迟,间隔短了服务器压力大。3 秒是个常见折中,但用户盯着屏幕等工单状态更新时,那 3 秒的空白足够让人再点一次刷新。
有个细节容易被忽略:轮询请求最好带上
If-Modified-Since或者 ETag。服务器返回 304 的话,响应体是空的,省带宽。我见过有人用轮询拉一个 200KB 的 JSON,每 5 秒一次,就为了看一个布尔值变没变。这种写法不是轮询的错,是人的错。另一个坑是页面切到后台。浏览器会限制定时器频率,
setInterval可能被降到一分钟一次。用户切回来发现数据没更新,骂的是前端。解决办法是监听visibilitychange,页面隐藏时暂停轮询,显示时立刻拉一次。代码多写二十行,体验好一截。轮询不是银弹,但它是一把可靠的螺丝刀。当你不需要毫秒级实时,当你的用户量不大,当你的技术栈老旧得动不了,它就在那里,简单、直接、不挑环境。我现在的项目里依然有轮询,跑在一个没人愿意重构的模块上。每次看到 Network 面板里那些规律跳动的请求,我都觉得它像老式挂钟——不优雅,但你知道它下一秒还会响。
顶: 4踩: 54






评论专区