window.localStorage在尝试写入数据超过容量限制时会抛异常,在Safari的隐私浏览模式下也会如此。因此,需要把调用放到try-catch语句里面:
try { localStorage.setItem('date', Date.now()); } catch (error) { reportError(error); }
有时候,需要把回调函数的代码放到try-catch里面,因为回调也可以调用其他会抛出异常的API。
listeners.forEach(function(lietener){ try { listener(); } catch (error) { reportError(error); } })
对于try-catch覆盖不到的地方,如果出现异常就只能通过window.onerror来捕获了:
window.onerror = function(errorMessage, scriptURI, lineNumber) { reportError({ message: errorMessage, script: scriptURI, line: lineNumber }); };
通常不使用window.addEventlistener或window.attachEvent的形式监听window.onerror。因为很多浏览器只实现了window.onerror,或者是只有window.onerror的实现是标准的。
通过window.onerror方式捕获异常,可以也只能获取异常的3个信息(参数)。而通过try-catch捕获到的异常,可以获取:错误类型(name)、错误消息(message)、脚本文件地址(script)、行号(line)、列号(column)、堆栈跟踪(stack),这些信息都在Error对象上(主流浏览器都支持)。
在自定义的Error对象中,error.message可以自由控制。
浏览器厂商也知道大家在使用 window.onerror 时受到的限制,所以开始往 window.onerror 上面添加新的参数。考虑到只有行号没有列号好像不是很对称的样子,IE 首先把列号加上了,放在第四个参数。然而大家更关心的是能否拿到完整的堆栈,于是 Firefox 说不如把堆栈放在第五个参数吧。但 Chrome 说那还不如把整个 Error 对象放在第五个参数,大家想读取什么属性都可以了,包括自定义属性。结果由于 Chrome 动作比较快,在 Chrome 30 实现了新的 window.onerror 签名,导致标准草案也就跟着这样写了。
window.onerror = function(errorMessage, scriptURI, lineNumber, columnNumber, error){
if(error){
reportError(error);
}else{
reportError({
message: errorMessage,
script: scriptURI,
line: lineNumber,
column: columnNumber
});
}
}