如何通过 AJAX 将 window.screen 信息安全可靠地传递至后端  第1张

`window.screen` 是不可直接序列化的 dom 对象,需手动提取关键属性(如宽高、色彩深度等)再发送,否则 ajax 请求会静默失败。

在 Web 开发中,常需将前端设备屏幕信息(如分辨率、可用区域、方向等)上报至后端用于统计分析、响应式策略或 A/B 测试。但直接赋值 data.w = window.screen 会导致 jQuery 的 $.ajax() 请求完全不发出——这是因为 window.screen 是一个非可枚举、不可序列化的宿主对象,其大部分属性(如 availWidth、height)虽可读取,但默认不被 JSON.stringify() 遍历(JSON.stringify 仅处理对象自身的可枚举自有属性,且要求值为基本类型、数组或可序列化对象)。

当 data 包含 window.screen 时,jQuery 在内部调用 jQuery.param()(非 JSON.stringify)处理 application/x-www-form-urlencoded 数据;而该方法对复杂对象(尤其是 DOM 接口实例)的序列化行为未定义,常导致参数丢失或请求中断,表现为 Network 面板无请求记录。

✅ 正确做法:显式提取所需属性,构建纯 JSON 友好对象:

const screenData = {
  availWidth: window.screen.availWidth,
  availHeight: window.screen.availHeight,
  width: window.screen.width,
  height: window.screen.height,
  colorDepth: window.screen.colorDepth,
  pixelDepth: window.screen.pixelDepth,
  orientationType: window.screen.orientation?.type || 'unknown',
  orientationAngle: window.screen.orientation?.angle || 0
};

$.ajax({
  method: 'POST',
  url: '/tested-route',
  crossDomain: true,
  contentType: 'application/x-www-form-urlencoded', // 注意:此处不应设为 false
  headers: {
    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('value'),
    'Accept': 'application/json'
  },
  data: {
    screen: JSON.stringify(screenData) // ✅ 序列化为字符串,后端解析
    // 或直接展开:...screenData
  },
  success: function(response) {
    console.log('Screen info sent successfully:', response);
  },
  error: function(jqXHR, textStatus, errorThrown) {
    console.error('AJAX failed:', textStatus, errorThrown);
  }
});

⚠️ 关键注意事项:

  • 不要将 contentType: false 与表单数据混用(它适用于 FormData 上传场景),此处应明确指定 'application/x-www-form-urlencoded';
  • window.screen.orientation 是实验性 API,需加空值检查(如 ?. 可选链)以避免 Safari 等环境报错;
  • 若后端使用 JSON 解析(如 Express 的 body-parser.json()),建议统一 contentType: 'application/json' 并发送 JSON.stringify({screen: screenData});
  • 避免传递敏感信息(如精确像素值可能助于指纹识别),生产环境应评估隐私合规性。

总结:永远不要直接传递 DOM 对象(window.screen、document、event 等)给 AJAX 的 data 字段。坚持“按需提取、显式构造、安全序列化”三原则,即可稳定、高效地完成前端设备信息上报。