如何检测Firefox伪造网络响应,避免错误展示数据加载时效?
问题分析与解决方案
核心原因
你遇到的是Firefox的**会话恢复(Session Restore)**特性:Firefox会保存关闭页面时的完整状态,包括已完成的fetch/XHR响应,重启浏览器恢复会话时,会直接重放这些响应,而非发起新的网络请求。此时你的代码会把dataLoaded设为当前时间,导致错误显示“Loaded 0s ago”,但实际数据是之前缓存的旧数据。
检测并修正的方法
以下几种方法可以在保留会话恢复功能的前提下,正确显示数据时效:
1. 利用Firefox特有的fromCache属性检测恢复响应
Firefox会给会话恢复的响应对象添加一个非标准的fromCache属性,你可以在fetch的第一个回调中检查这个属性:
let dataLoaded = null; let isRestoredData = false; function loadData() { fetch(url).then((response) => { // 检测是否是会话恢复的缓存响应 isRestoredData = response.fromCache; if (!isRestoredData) { // 仅新请求设置当前时间 dataLoaded = (new Date()).getTime() / 1000; } else { dataLoaded = null; } return response.json(); }).then((responsejson) => { // 若数据自带更新时间,可直接替换dataLoaded if (isRestoredData && responsejson.lastUpdated) { dataLoaded = responsejson.lastUpdated / 1000; } // 处理数据逻辑 }); } loadData(); setInterval(() => { if (dataLoaded == null) { $('#dataAge').innerText = isRestoredData ? 'Loaded from session restore' : ''; return; } const now = (new Date()).getTime() / 1000; $('#dataAge').innerText = `Loaded ${Math.floor(now - dataLoaded)}s ago`; }, 15000);
2. 让服务器返回数据生成时间戳
如果能控制后端服务,在响应头中添加自定义头(比如X-Data-Created-Time),记录数据实际生成的时间戳。不管是新请求还是会话恢复的响应,这个头都会被保留,直接用它计算时效:
let dataLoaded = null; function loadData() { fetch(url).then((response) => { // 从响应头获取服务器提供的时间戳 const serverTimestamp = response.headers.get('X-Data-Created-Time'); dataLoaded = serverTimestamp ? parseInt(serverTimestamp) / 1000 : (new Date()).getTime() / 1000; return response.json(); }).then((responsejson) => { // 处理数据逻辑 }); } loadData(); // 定时器逻辑不变,dataLoaded始终为数据真实生成时间
3. 直接使用数据自带的更新时间
如果返回的responsejson本身包含数据更新时间(比如lastUpdated字段),彻底放弃用本地时间标记加载时间,直接用这个字段的值:
let dataLoaded = null; function loadData() { fetch(url).then((response) => response.json()) .then((responsejson) => { // 用数据自带的更新时间计算时效 dataLoaded = responsejson.lastUpdated / 1000; // 处理数据逻辑 }); }
这种方式完全不受会话恢复影响,因为数据里的时间戳是固定的,无论新请求还是恢复响应,都会用同一时间计算时效。
额外说明
你提到添加随机URL参数可以禁用该行为,这是因为Firefox无法找到匹配的缓存响应,所以不会重放。但这种方法会丢失会话恢复的便利性,不推荐使用。
内容的提问来源于stack exchange,提问作者Luc
相关产品推荐
相关产品推荐

