寻求Safari与Firefox兼容的navigator.connection替代网络信息方案
问题说明
navigator.connection(Network Information API)的浏览器支持度有限:Safari桌面版完全不支持,Firefox仅在Android移动端部分支持,因此需要替代方案来获取下载速度。
可行替代方案
方案1:兼容前缀API fallback
部分浏览器提供了带前缀的API,可先尝试兼容覆盖部分场景:
getConnectionDetails() { const con = navigator.connection || navigator.mozConnection || navigator.webkitConnection; if (con) { return { downlink: con.downlink, effectiveType: con.effectiveType, rtt: con.rtt }; } // 不支持时走主动测速逻辑 return {}; }
注:该方案无法解决Safari桌面版的支持问题,仅作为基础兼容补充。
方案2:主动下载资源测速(核心方案)
通过下载已知大小的资源,计算耗时推导下载速度,适用于所有现代浏览器。
实现思路
- 准备固定大小的测速资源(推荐用无内容的空白文件,或直接用Data URI避免跨域)
- 记录下载开始时间
- 完成下载后计算耗时,结合文件大小换算为Mbps单位的速度
- 可选:添加随机参数避免缓存,多次测速取平均值提升准确性
代码示例
// 测速函数,返回Promise,resolve结果为下载速度(Mbps) async function getDownloadSpeed() { // 生成100KB的Data URI作为测速资源(大小可按需调整) const testUrl = 'data:application/octet-stream;base64,' + 'A'.repeat(100 * 1024 / 2); const startTime = performance.now(); try { const response = await fetch(testUrl, { cache: 'no-store' }); if (!response.ok) throw new Error('测速资源下载失败'); // 读取内容确保下载完成 await response.arrayBuffer(); const endTime = performance.now(); const duration = (endTime - startTime) / 1000; // 转换为秒 const fileSizeInBytes = 100 * 1024; // 100KB // 计算Mbps:(字节数 * 8) / (1024*1024) / 耗时 const speedMbps = (fileSizeInBytes * 8) / (1024 * 1024) / duration; return Math.round(speedMbps * 10) / 10; // 保留一位小数 } catch (err) { console.error('测速失败:', err); return null; } } // 使用示例 getDownloadSpeed().then(speed => { if (speed !== null) { console.log(`当前下载速度:${speed} Mbps`); } });
优化建议
- 调整资源大小:低速网络用10KB小文件,高速网络用1MB大文件,平衡测速时间与准确性
- 多次测速取平均:连续测3次取中间值或平均值,降低单次波动影响
- 异常处理:网络断开时返回默认值或提示用户
方案3:推断网络类型(可选)
如果需要类似effectiveType的网络类型标识,可根据测速结果推断:
function getNetworkType(speedMbps) { if (speedMbps < 1) return '2g'; if (speedMbps < 4) return '3g'; return '4g'; // 包含5G、有线等高速网络 }
内容的提问来源于stack exchange,提问作者Snooky
相关产品推荐
相关产品推荐

