摘要

  • W3C 于 2013 年 10 月发布的首份 Beacon 公开草案,直接列出网页离开时拖慢导航的旧招:同步 XMLHttpRequest、图片加载和空转循环。
  • 2022 年 8 月的候选推荐草案描述 navigator.sendBeacon():网页交出一份小型单向报告,浏览器排队处理,读者照常离开。

网页关门时也有记账员。访客刚走到门口,它想赶紧把最后一条事件、一次会话摘要或诊断数据送回服务器。内容也许只有几行,态度却像查行李:单据没送到,谁也别想迈步。读者等的不是下一页,而是上一页的办公室流程。

W3C 在 2013 年 10 月 29 日发布的首份 Beacon 公开工作草案把这件烦事写得很直白。网页卸载时发出的普通异步请求可能被浏览器丢下。开发者为了提高送达机会,有时改用同步 XMLHttpRequest,让离开动作等请求结束;有人借图片加载争取时间;还有人写什么也不做的循环,纯靠浪费时间挡门。规范指出,下一页会因此显得更慢。

早期草案提出的不是一名跑得更快的记账员,而是换个收件人。网页把数据交给用户代理,由后者择机传送。2013 年文本里的方法叫 beacon,调用形式与后来的 navigator.sendBeacon() 不同。把不同年代的代码混成一段会误读历史;真正延续下来的想法,是把发送任务从即将消失的页面转交给仍能安排网络工作的浏览器。

为什么最后一刻才报账?一次会话的结尾可能产生先前没有的事件。每发生一件事就立即请求服务器,会消耗网络与电量;攒到最后,又怕页面先消失。旧做法让读者承担这道两难题的成本。Beacon 让浏览器代管小份报告,把网页的统计需要与读者的离开动作拆开。

W3C 于 2022 年 8 月 3 日发布的候选推荐草案描述 navigator.sendBeacon(url, data)。请求是异步、非阻塞、单向的。用户代理可以按照网络负载安排优先级,也可以合并发送以节省移动设备能耗。读者点开下一页、界面响应手势、动画继续播放,都不必排在这份小报告后面。浏览器像信使接过信,客人不必站在门口看它上路。

2022 年示例监听的是 visibilitychange,在文档变成隐藏状态时发出会话报告。移动设备上,页面可能先退到后台,随后进程被系统结束,正式的 unload 事件未必出现。与其等待一场可能不会举行的告别仪式,不如在页面隐去时把信封交出来。页面可见性提供时机,Beacon 负责排队传送,两者各司其职。

返回值尤其容易被讲错。sendBeacon() 返回 true,说明浏览器接受数据进入待发送队列。服务器是否收到,须看服务器自己的记录。这个接口没有给网页处理响应的回调。信使收下信封时可以说“拿到了”,却没法当场出示远方的签收单。把排队当成送达,只会制造一份漂亮但虚假的统计。

信封也有大小。2022 年文本把 Beacon 的网络请求接到带 keepalive 的 fetch 机制,并限制待发送数据量。需要自定义方法、请求头或读取响应的应用,可以选择相应的 fetch 流程。小信封的价值在于轻便;把整间仓库塞给它,既不合设计,也妨碍下一位客人出门。

W3C 的发布历史记录了 2013 年的首份公开草案、2017 年的候选推荐快照和 2022 年的候选推荐草案。这些是规范文本的时间点。贯穿其间的问题始终具体:网页想保存一笔临别记录,谁来负责最后的发送,谁又不该为此停下脚步?

好的改变往往表现为少了一次等待。下一页照常打开,上一页的统计也有了合适的交接方式。门已经打开,记账员可以继续写,读者无需坐在前台等它盖章。