利用window.onerror捕获并上报JS错误及跨域处理方案

作者:工具松鼠

时间:2026-10-29

浏览:252

本文详解如何使用window.onerror捕获JavaScript运行时错误,并重点解决跨域脚本加载时的错误信息屏蔽问题。通过配置script标签的crossorigin属性及服务端Access-Control-Allow-Origin响应头,可实现跨域JS错误的完整捕获与上报,适用于前端监控系统的构建。

文章目录

window.onerror基础用法与Demo

近期有2048游戏用户反馈,在iPhone 4S、iOS 5.1设备上打开游戏后无法游玩,表现为仅有游戏面板,数字未初始化且不可移动。尝试通过微信调起Safari浏览器打开,问题依旧存在。鉴于游戏大量使用了HTML5特性,推测可能是JS报错导致。那么如何捕获此类信息呢?答案是使用window.onerror。

查阅W3C规范中关于window.onerror的方法体介绍:

window.onerror基础用法与Demo

这意味着,我们可以将window.onerror方法定义如下:


/** 
 * @param {String} errorMessage  错误信息 
 * @param {String} scriptURI   出错的文件 
 * @param {Long}  lineNumber   出错代码的行号 
 * @param {Long}  columnNumber  出错代码的列号 
 * @param {Object} errorObj    错误的详细信息,Anything 
 */
window.onerror = function(errorMessage, scriptURI, lineNumber,columnNumber,errorObj) { 
  // TODO 
}

但在实际使用中需注意浏览器兼容性问题,并非所有浏览器都支持参数列表中的所有参数。Chrome等浏览器作为标准草案的领跑者,可以直接使用这些参数。

因此,可以编写一个小Demo进行测试:


<!DOCTYPE html> 
<html> 
<head> 
  <title>Js错误捕获</title> 
  <script type="text/javascript"> 
  /** 
   * @param {String} errorMessage  错误信息 
   * @param {String} scriptURI   出错的文件 
   * @param {Long}  lineNumber   出错代码的行号 
   * @param {Long}  columnNumber  出错代码的列号 
   * @param {Object} errorObj    错误的详细信息,Anything 
   */ 
  window.onerror = function(errorMessage, scriptURI, lineNumber,columnNumber,errorObj) { 
    console.log("错误信息:" , errorMessage); 
    console.log("出错文件:" , scriptURI); 
    console.log("出错行号:" , lineNumber); 
    console.log("出错列号:" , columnNumber); 
    console.log("错误详情:" , errorObj); 
  } 
  </script> 
</head> 
<body> 
  <script type="text/javascript" src="error.js"></script> 
</body> 
</html>

其中error.js文件的内容简单定义为:

throw new Error("出错了!"); 在浏览器中运行后,打开控制台,显示如下:

window.onerror基础用法与Demo

跨域脚本错误捕获问题

由此可见,这些数据均可用于上报。 当然,上述error.js与HTML页面处于同域名下。如果error.js不在同域下,情况会如何?我们将error.js的引用修改为:

<script type="text/javascript" src="https://doitbegin.duapp.com/error.js"></script> 再次打开控制台,我们看到:

window.onerror基础用法与Demo

此时,window.onerror方法仅捕获到一个errorMessage,且为固定字符串,毫无参考价值。查阅资料(Webkit源码)发现,在浏览器实现script资源加载时进行了同源策略判断。如果是非同源资源,errorMessage会被写死为“Script error”:

window.onerror基础用法与Demo

跨域错误上报解决方案

好在script标签有一个crossorigin属性,设置它可以显示比较详细的错误信息。我们尝试将script标签修改为:

<script type="text/javascript" src="https://doitbegin.duapp.com/error.js" crossorigin></script> 刷新页面,此时看到console中的输出如下:

window.onerror基础用法与Demo

出现这个error也不意外,既然设置了error.js为crossorigin,那error.js的HTTP Response Header也必须设置非同源可访问。为了方便设置Header,把error.js做一个小改动,更名为:error-js.php。


<?php 
  header('Access-Control-Allow-Origin:*'); 
  header('Content-type:text/javascript'); 
?> 
throw new Error('出错了'); 

此时刷新页面,看到console中的输出就已经正常了,所有信息都能正常捕获:

window.onerror基础用法与Demo

OK,技术细节分析结束!我2048游戏静态资源是放到静态域(非同源)下的,所以要想通过window.onerror捕获错误信息,就得按照上面的最后一种情况来操作了:

1、添加script的crossorigin属性

2、配置一下服务器,设置静态资源Javascript的Response为Access-Control-Allow-Origin

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章