javascript的異常處理

先了解一下javascript原生的異常類型

1、SyntaxError //解析代碼時發(fā)生的語法錯誤
2、ReferenceError //引用一個不存在的變量時發(fā)生的錯誤
3、RangeError //當(dāng)一個值超出有效范圍時發(fā)生的錯誤
4、TypeError //變量或參數(shù)不是預(yù)期類型時發(fā)生的錯誤
5、URIError //URI相關(guān)函數(shù)的參數(shù)不正確時拋出的錯誤
6、EvalError //eval函數(shù)沒有被正確執(zhí)行時,會拋出EvalError錯誤
7、Error:最普通的異常

Error對象

JavaScript原生提供一個Error構(gòu)造函數(shù),所有拋出的錯誤都是這個構(gòu)造函數(shù)的實(shí)例。Error對象的實(shí)例必須含有message屬性,提示出錯的信息:

var err = new Error('出錯了');
err.message // "出錯了"

此外,部分javascript引擎還提供了其他兩個非標(biāo)準(zhǔn)的屬性
1.name : 錯誤名稱
2.stack : 錯誤的堆棧

自定義異常

除了上述提到的原生異常類型,javascript還允許我們自己定制異常,通過創(chuàng)建一個異常對象,然后讓其繼承Error對象即可

function newError(message){
  this.message = message;
  this.name = "newError";
}
newError.prototype = new Error();
newError.prototype.constructor = newError;
var demo = new newError("自定義異常");

try-catch結(jié)構(gòu)

try {
  //...
} catch (e) {
  console.log(e.name + ": " + e.message);
  console.log(e.stack);
}

try語句內(nèi)存放的是需要檢測異常的代碼段,catch代碼塊捕獲錯誤之后,程序不會中斷,會按照正常流程繼續(xù)執(zhí)行下去。
比如:

openFile();
try{
  writeFile(); //檢測函數(shù)運(yùn)行是否異常
}catch(e){
  handleError(e); //捕獲到異常后處理
}

try-catch-finally結(jié)構(gòu)

引入finally的目的是為了讓代碼更加健壯,finally內(nèi)的代碼段是必須執(zhí)行的部分,不過在代碼運(yùn)行出現(xiàn)異常和沒有異常的場合下執(zhí)行的方式不同:假如try語句內(nèi)代碼未出現(xiàn)異常,那么正常執(zhí)行finally內(nèi)的代碼段;如果出現(xiàn)了異常,那么先執(zhí)行catch內(nèi)的異常處理,后執(zhí)行finally內(nèi)的語句。
接著上面的例子:

openFile();
try{
  writeFile(); //檢測函數(shù)運(yùn)行是否異常
}catch(e){
  handleError(e); //捕獲到異常后處理
}finally{
  closeFile();
}

注意:如果catch內(nèi)含有return,那么出現(xiàn)異常時先執(zhí)行catch內(nèi)位于return之前的代碼,catch內(nèi)return語句后的代碼不會執(zhí)行,然后跳轉(zhuǎn)到finally。

拋出異常-throw

throw語句的作用是中斷程序執(zhí)行,拋出一個意外或錯誤。它接受一個表達(dá)式作為參數(shù),可以拋出各種值。

function throwIt(exception) {
 try {
   throw exception;
 } catch (e) {
   console.log('Caught: '+ e);
 }
}

throwIt(3);
// Caught: 3
throwIt('hello');
// Caught: hello
throwIt(new Error('An error happened'));
// Caught: Error: An error happened

加入判斷語句:

var n = 100;

try {
  throw n;
} catch (e) {
  if (e <= 50) {
    // ...
  } else {
    throw e;
  }
}

catch在捕獲到throw拋出的異常后,還是按照原本方式執(zhí)行

異常類型的檢測

上述我們已經(jīng)有了在try-catch語句內(nèi)加入判斷的例子,生活中有時我們需要針對不同的異常做不同的處理,就可以借鑒前面的方式。

try {
  foo.bar();
} catch (e) {
  if (e instanceof EvalError) {
    console.log(e.name + ": " + e.message);
  } else if (e instanceof RangeError) {
    console.log(e.name + ": " + e.message);
  }
  // ...
}

全局異常處理window.onerror

上述提到的try-catch(finally)結(jié)構(gòu)只適合在代碼塊內(nèi)執(zhí)行,無法做到全局異常檢測,window.onerror可以做到。
結(jié)構(gòu):

window.onerror = function (message, source, lineno, colno, error) { }

message:異常信息(字符串)
source:發(fā)生異常的腳本URL(字符串)
lineno:發(fā)生異常的行號(數(shù)字)
colno:發(fā)生異常的列號(數(shù)字)
error:Error對象(對象)

兼容性:IE9及以下只支持前面3個參數(shù)
Chrome 13+
Firefox 6.1+
Safari 5.1+
Opera 11.61+
IE10+
都支持全部

try {
    setTimeout(() => {
        throw new Error("some message");
    }, 0);
} catch (err) {
    console.log(err);
}
/*******/
window.onerror = (msg, url, line, col, err) => {
    console.log(err);
}
setTimeout(() => {
    throw new Error("some message");
}, 0);
// Error: some message

列出一個window.onerror的兼容性寫法:

window.onerror = function(errorMessage, scriptURI, lineNumber,columnNumber,errorObj) {
    var errorStr = '', error = {};
    error.errorMessage = errorMessage;
    error.scriptURI = scriptURI;
    error.lineNumber = lineNumber;
    error.columnNumber = columnNumber || '';
    error.errorObj = errorObj || '';
    error.userAgent = window.navigator.userAgent;
    error.pageUrl = window.location.href;
    errorStr = ' errorMessage: ' + error.errorMessage + '\n scriptURI: ' + error.scriptURI
                + '\n lineNumber: ' + error.lineNumber + '\n columnNumber: ' + error.columnNumber
                + '\n errorDescription: ' + error.errorDescription + '\n userAgent: ' + error.userAgent
                + '\n pageUrl: ' + error.pageUrl;
    
    console.log(errorStr);
    new Image().src = '/errorLog/index';
}

在chrome中,window.onerror能檢測從別的域引用的腳本文件中的異常,并且將這些異常標(biāo)記為Script error,如果不想處理其他域的腳本文件,可以在代碼中用Script error標(biāo)記將其過濾。然而如果異常被try-catch包裹,chrome也無法檢測到異常。在其他瀏覽器中不會引入跨域js異常,也只能獲取到一個簡單的 Script Error信息,沒有什么實(shí)際意義。

解決方案:
1.給應(yīng)用內(nèi)所需的<script>標(biāo)簽添加 crossorigin 屬性,比如:<script type=”text/javascript” src=”/error.js” crossorigin></script>;
2.在 js 所在的 cdn 服務(wù)器上添加 Access-Control-Allow-Origin: *HTTP 頭;
3.使用 throw new Error(“error message here”)。
<script>
    window.onerror = function () {
        console.log(arguments)
        return true;
    }
    throw new Error('show error');
</script>
Paste_Image.png

值得一提的是,頁面中可能有好幾個 script 標(biāo)簽, window.onerror 這個錯誤監(jiān)聽一定要放到最前頭,否則將監(jiān)聽不到錯誤。如果將throw new Error放前頭,throw new Error('show error');將直接報錯,也就無法往下執(zhí)行

參考:http://javascript.ruanyifeng.com/grammar/error.html
https://segmentfault.com/a/1190000011481099#articleHeader4
https://github.com/hawx1993/tech-blog/issues/13
http://www.frontfans.com/archives/139
http://caibaojian.com/toutiao/7963

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容