前端的水平線,錯誤處理和調試

本章內容

  • 理解瀏覽器報告的錯誤
  • 處理錯誤
  • 調試JavaScript代碼

錯誤處理

錯誤處理在程序設計中的重要性是必定的。任何有影響力的Web應用程序都須要一套完善的錯誤處理機制。php

try-catch語句

try {
    // 可能會致使錯誤的代碼
} catch (e) {
    // 在錯誤發生時怎麼處理
}
複製代碼

錯誤類型

執行代碼期間可能會發生的錯誤有多種類型。每種錯誤都有對應的錯誤類型,而當錯誤發生時,就會拋出相應類型的錯誤對象。
ECMA-262定義了下列7種錯誤類型:編程

  • Error跨域

  • EvalError瀏覽器

  • RangeErrorbash

  • SyntaxError服務器

  • ReferenceErrorapp

  • TypeError函數

  • URIErrorui

  • RangeError類型的錯誤在數值超出相應範圍時觸發:編碼

try {
    let items1 = new Array(-20);
var items2 = new Array(Number.MAX_VALUE);
} catch (e) {
    console.dir(e)
}
複製代碼
  • 在找不到對象的狀況下,會發生ReferenceError(這種狀況下,會直接致使人所共知的「object expected」瀏覽器錯誤)。一般,在訪問不存在的變量時,就會發生這種錯誤:
try {
    let obj = x;
} catch (e) {
    console.dir(e)
}
複製代碼
  • SyntaxError類型, 當咱們把語法錯誤的JavaScript字符串傳入eval()函數時,就會致使此類錯誤。
eval('a++ b')
複製代碼
  • TypeError類型在JavaScript中會常常用到,在變量中保存着意外的類型時,或者在訪問不存在的方法時,都會致使這種錯誤。錯誤的緣由雖然多種多樣。**最常發生類型錯誤的狀況,就是傳遞給函數的參數事先未經檢查,結果傳入類型與預期類型不相符。
Function.prototype.toString.call('name')   // 拋出typeError
複製代碼
  • 在使用encodeURI()或decodeURI(),而URI格式不正確時,就會致使URIError錯誤。這種錯誤不多見,由於前面說的這兩個函數的容錯性很是高。

利用不一樣錯誤類型,能夠獲悉更多有關異常的信息,從而有助於對錯誤做出恰當的處理。

try {
    // ......
} catch (e) {
    if (e instanceof TypeError) {
        // 處理類型錯誤
    } else if (e instanceof ReferenceError) {
        // 處理引用錯誤
    } else {
        // 處理其餘類型的錯誤
    }
}
複製代碼

在跨瀏覽器編程中,檢查錯誤類型是肯定處理方式的最簡便途徑;包含在message屬性中的錯誤消息會因瀏覽器而異。

合理使用try-catch

使用try-catch最適合處理那些咱們沒法控制的錯誤。假設你在使用一個大型JavaScript庫中的函數,該函數可能會有意無心地拋出一些錯誤。因爲咱們不能修改這個庫的源代碼,因此大可將對該函數的調用放在try-catch語句當中。

拋出錯誤

與try-catch語句相配的還有一個throw操做符,用於隨時拋出自定義錯誤。

throw new Error('Something bad happend')
複製代碼

上面這行代碼拋出一個通用錯誤,帶有一條自定義錯誤消息。也能夠像下面使用其餘錯誤類型,也能夠模擬出相似的瀏覽器錯誤。

throw new SyntaxError('I dont like your syntax');

throw new TypeError('What type of variable do you take me for?');

throw new RangeError('Sorry, you just dont have the range')

throw new EvalError('That doesnt evaluate.')

throw new URIError('Uri, is that you?');

throw new ReferenceError('You didnt cite your references properly');
複製代碼

錯誤事件

window.onerror = function (message, url, line) {
    // 處理錯誤
}
複製代碼

處理錯誤的策略

常見的錯誤類型

錯誤處理的核心,是首先要知道代碼裏會發生什麼錯誤。因爲JavaScript是鬆散類型的,並且也不驗證函數的參數,所以錯誤只會在代碼運行期間出現。通常須要關注三種錯誤:

  • 類型轉換錯誤
  • 數據類型錯誤
  • 通訊錯誤

類型轉換錯誤

全等操做符知道要比較的是兩種不一樣的數據類型,於是直接返回false。

數據類型錯誤

Javascript是鬆散類型的,也就是說,在使用變量和函數參數以前,不會對它們進行比較以確保它們的數據類型正確。

通訊錯誤

Javascript與服務器之間的任何一次通訊,都有可能會產生錯誤。

  • 第一種通訊錯誤與格式不正確的URL或發送的數據有關。最多見的問題是在將數據發送給服務器以前,沒有使用encodeURIComponent()對數據進行編碼。
function addQueryString(url, name, value) {
            if (url.indexOf('?') === -1) {
                url += '?';
            } else {
                url += '&';
            }

            url += `&${encodeURIComponent(name)} = ${encodeURIComponent(value)}`;
            
            return url;
        }
複製代碼

使用這個函數而不是手工構建URL,能夠確保編碼正確並避免相關錯誤。

區分致命錯誤和非致命錯誤

任何錯誤處理策略中最重要的一部分,就是肯定錯誤是否致命。對於非致命錯誤,能夠根據下列一或多個條件來肯定:

  • 不影響用戶的主要任務
  • 隻影響頁面的一部分
  • 能夠恢復
  • 重複相同操做能夠消除錯誤

把錯誤記錄到服務器

開發Web應用程序中的一種常見的作法,就是集中保存錯誤日誌,以便查找重要錯誤的緣由。

要創建這樣一種JavaScript錯誤記錄系統,首先須要在服務器上建立一個頁面,用於處理錯誤數據。這個頁面的做用無非就是從查詢字符中取得數據,而後再將數據寫入錯誤日誌中。這個頁面可能會使用以下所示的函數:

function logError (lev, msg) {
    let img = new Image();
    img.src = `log.php?e`
}
複製代碼

這個logError()函數接收兩個參數:表示嚴重程度的數值或字符串及錯誤消息。其中使用了Image對象來發送請求,這樣作很是靈活,主要表現以下幾方面:

  • 全部瀏覽器都支持Image對象,包括那些不支持XMLHttpRequest對象。
  • 能夠避免跨域限制。
  • 在記錄錯誤的過程當中出問題的機率比較低。大多數Ajax通訊都是由JavaScript庫提供的包裝函數來處理的,若是庫代碼自己有問題,而你還在依賴該庫記錄錯誤,可想而知,錯誤消息是不可能獲得記錄的。

小結

錯誤處理相當重要。不能提早預測到可能發生的錯誤,不能提早採起恢復策略,可能致使較差的用戶體驗。

下面是幾種避免瀏覽器響應JavaScript錯誤的方法。

  • 在可能發生錯誤的地方使用try-catch語句,這樣你還有機會以適當的方式對錯誤給出響應。
  • 使用window.onerror事件處理程序,這種方式能夠接受try-catch不能處理的全部錯誤。

另外,對任何Web應用程序都應該分析可能發生的錯誤。JavaScript中發生錯誤的主要緣由以下。

  • 類型轉換
  • 未充分檢測數據類型
  • 發送給服務器或從服務器接收到的數據有錯誤
相關文章
相關標籤/搜索