处理 JS 中的异常

前端异常处理的思路是在执行的入口处 try catch,以此来减少由致命错误导致的程序崩溃,错误上报等。

这样的话我们需要知道 js 程序的执行入口。一是正常的执行流程,二是异步回调函数。在 js 中正常的执行流程比较少也比较好处理。但是回调函数随处可见。所以以下着重写一下我是怎么处理在回调函数中的异常。

回调函数又分为事件的回调函数和网络请求的回调函数。

其中网络请求的回调函数比较好处理,每个请求都调用同一个方法。比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function getJson(url, successCallback, failCallback) {
mask();
$.ajax({
url: url,
method: "GET",
success: function(data) {
try {
if (data.success) {
successCallback(data.data);
} else {
failCallback(data.message)
console.warn(data.message)
}
} catch(e) {
console.error(e)
}
},
error: function(response) {
try {
failCallback(data.message)
console.warn(data.message)
} catch (e) {
console.error(e)
}
}
})
}

如果你是用 fetch API 那么一个 catch() 方法就可以搞定上面至少需要两个 catch() 方法才能搞定的异常。

事件的回调函数比较难处理,DOM 的事件散布在各处,没有一个统一的点收集这些事件。这怎么处理呢比较头疼。
一,可以在 DOM 加载完的时候改写

1
2
3
4
5
6
7
8
var originalEvent = dom.onclick;
dom.onclick = function (e) {
try {
originalEvent(e)
} catch (e) {
console.error(e)
}
}

二,但是如果你是通过 addEventListener() 来添加监听函数,那么最好不是直接使用 addEventListener(),而是自己创建一个方法封装一下。比如:

1
2
3
4
5
6
7
8
9
function bind(node, event_name, handler, useCapture) {
node.addEventListener(event_name, function(e) {
try {
handler.call(node, e)
} catch (e) {
console.error(e)
}
})
}

如果你是使用 React,那么事件监听函数直接用下面代码即可:

1
2
3
4
5
6
7
8
9
10
import ReactErrorUtils from 'react-dom/lib/ReactErrorUtils'
ReactErrorUtils.invokeGuardedCallback = function (name, func, a) {
try {
func(a);
} catch (x) {
// do somethin
console.error(x)
}
}

参考

https://stackoverflow.com/questions/1421257/intercept-javascript-event
https://reactjs.org/docs/events.html (SyntheticEvent)