如何優(yōu)雅處理前端異常?
(給前端大學(xué)加星標(biāo),提升前端技能.)
前端一直是距離用戶最近的一層,隨著產(chǎn)品的日益完善,我們會更加注重用戶體驗(yàn),而前端異常卻如鯁在喉,甚是煩人。作者: Jartto's blog
http://jartto.wang/2018/11/20/js-exception-handling/
一、為什么要處理異常?
異常是不可控的,會影響最終的呈現(xiàn)結(jié)果,但是我們有充分的理由去做這樣的事情。- 增強(qiáng)用戶體驗(yàn);
- 遠(yuǎn)程定位問題;
- 未雨綢繆,及早發(fā)現(xiàn)問題;
- 無法復(fù)線問題,尤其是移動端,機(jī)型,系統(tǒng)都是問題;
- 完善的前端方案,前端監(jiān)控系統(tǒng);
二、需要處理哪些異常?
對于前端來說,我們可做的異常捕獲還真不少。總結(jié)一下,大概如下:- JS 語法錯(cuò)誤、代碼異常
- AJAX 請求異常
- 靜態(tài)資源加載異常
- Promise 異常
- Iframe 異常
- 跨域 Script error
- 崩潰和卡頓
三、Try-Catch 的誤區(qū)
try-catch 只能捕獲到同步的運(yùn)行時(shí)錯(cuò)誤,對語法和異步錯(cuò)誤卻無能為力,捕獲不到。- 同步運(yùn)行時(shí)錯(cuò)誤:
try {輸出:
let name = 'jartto';
console.log(nam);
} catch(e) {
console.log('捕獲到異常:',e);
}
捕獲到異常:ReferenceError: nam is not defined
at:3:15
- 不能捕獲到具體的語法錯(cuò)誤,只有一個(gè)語法錯(cuò)誤提示。我們修改一下代碼,刪掉一個(gè)單引號:
try {輸出:
let name = 'jartto;
console.log(nam);
} catch(e) {
console.log('捕獲到異常:',e);
}
Uncaught SyntaxError: Invalid or unexpected token
不過語法錯(cuò)誤在我們開發(fā)階段就可以看到,應(yīng)該不會順利上到線上環(huán)境。
- 異步錯(cuò)誤
try {我們看看日志:
setTimeout(() => {
undefined.map(v => v);
}, 1000)
} catch(e) {
console.log('捕獲到異常:',e);
}
Uncaught TypeError: Cannot read property 'map' of undefined并沒有捕獲到異常,這是需要我們特別注意的地方。
at setTimeout (<anonymous>:3:11)
四、window.onerror 不是萬能的
當(dāng) JS 運(yùn)行時(shí)錯(cuò)誤發(fā)生時(shí),window 會觸發(fā)一個(gè) ErrorEvent 接口的 error 事件,并執(zhí)行 window.onerror()。/**
* @param {String} message 錯(cuò)誤信息
* @param {String} source 出錯(cuò)文件
* @param {Number} lineno 行號
* @param {Number} colno 列號
* @param {Object} error Error對象(對象)
*/
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕獲到異常:',{message, source, lineno, colno, error});
}
- 首先試試同步運(yùn)行時(shí)錯(cuò)誤
window.onerror = function(message, source, lineno, colno, error) {可以看到,我們捕獲到了異常:
// message:錯(cuò)誤信息(字符串)。
// source:發(fā)生錯(cuò)誤的腳本URL(字符串)
// lineno:發(fā)生錯(cuò)誤的行號(數(shù)字)
// colno:發(fā)生錯(cuò)誤的列號(數(shù)字)
// error:Error對象(對象)
console.log('捕獲到異常:',{message, source, lineno, colno, error});
}
Jartto;

- 再試試語法錯(cuò)誤呢?
window.onerror = function(message, source, lineno, colno, error) {控制臺打印出了這樣的異常:
console.log('捕獲到異常:',{message, source, lineno, colno, error});
}
let name = 'Jartto
Uncaught SyntaxError: Invalid or unexpected token什么,竟然沒有捕獲到語法錯(cuò)誤?
- 懷著忐忑的心,我們最后來試試異步運(yùn)行時(shí)錯(cuò)誤:
window.onerror = function(message, source, lineno, colno, error) {控制臺輸出了:
console.log('捕獲到異常:',{message, source, lineno, colno, error});
}
setTimeout(() => {
Jartto;
});
捕獲到異常:{message: "Uncaught ReferenceError: Jartto is not defined", source: "http://127.0.0.1:8001/", lineno: 36, colno: 5, error: ReferenceError: Jartto is not defined
at setTimeout (http://127.0.0.1:8001/:36:5)}
- 接著,我們試試網(wǎng)絡(luò)請求異常的情況:
翔田千里无码一区二区三区 | 国产婷婷在线播放 | 色婷在线视频 | 夜夜躁狠狠躁日日躁 | 国产无码乱伦视频 |
