錯誤處理
try-catch語句
在使用try-catch時,我們通常是把可能會出錯的代碼放在try語句塊中,把錯誤處理程序放在catch語句塊中。
try {
}
catch(err){
}
那麼,當我們執行try語句塊中的代碼遇到錯誤時,會跳出try語句塊,然後執行catch中的代碼。通過上面的代碼可以發現,catch會接收一個錯誤相關的對象err,err中存有與錯誤有關的信息,可能不同瀏覽器中err實際包含的內容有着不同,但是所有的瀏覽器均支持一個錯誤信息的message屬性。可以通過err.message獲取到。
finally子句
如果在try-catch後面添加了一個finally子句,那麼不管try中的代碼執行會不會出錯,都會執行finally中的代碼。也就是說,不管執行了try,還是catch,不管try或catch中的語句是什麼——甚至包括return語句,都會執行finally中的代碼,那麼就是說,如果存在finally,那麼try或catch中的return會失效。
try {
return 1;
}
catch(err)
{
return -1;
}
finally {
return 0;
}
通過上面的講解我們可以知道,結果爲:0
錯誤類型
代碼執行過程中會出現的錯誤主要有以下幾種:
- Error 基類型,其他類型的錯誤均繼承自該類型。
- RangeError 數值超出相應的範圍,如new Array(-20)
- EvalError 使用eval()函數出錯時拋出,即沒有吧eval()函數當成函數直接調用
- ReferenceError 引用錯誤
var obj = x ; //ReferenceError: x is not defined.
- SyntaxError 語法錯誤
- TypeError 類型錯誤,執行於特定操作時,變量類型不符合要求。
- URIError URI格式不正確
throw拋出錯誤
通過throw可以隨時拋出自定義錯誤。
- 拋出錯誤的時機
在出現某種特定的已知錯誤條件,導致函數無法正常執行時拋出錯誤。常見情況爲,函數參數的傳遞。比如我們希望函數接收一個數組參數,在函數內部有直接調用數組方法。那麼如果傳進來一個數字,就會出錯。因此可以加入一個判斷語句,如果傳入的參數不爲數組,則手動拋出一個錯誤。 - try-catch與throw
try-catch最適合處理那些我們無法控制的錯誤。比如:當你使用別人的代碼時,可能無法修改源碼,那麼這種情況下,就可以把代碼運行在try語句塊中。throw則是更多可以用在已知錯誤條件的情況。
另外,需要注意的是,當使用try-catch時,我們是希望自己對錯誤進行處理,而不是使用瀏覽器默認的錯誤處理。throw拋出錯誤的目的則是提供錯誤發生的具體原因的消息。(比如,我們可以在throw拋出的錯誤中添加出錯的函數及錯誤原因,這樣,當代碼量比較多時,可以快速定位錯誤的位置。)
error事件
所有不通過try-catch處理的錯誤都會觸發window的error事件。要制定window的error事件,必須使用DOM0級的onerror,他沒有遵循DOM2級事件的標準格式。
window.onerror = function(message,url,line){
}
通過代碼可以看到,onerror事件的回調函數有三個參數:錯誤信息,錯誤的URL,錯誤所在的行號。
圖像也支持error事件,當src指定的URL不能返回可識別的圖像格式,就會觸發事件。事件的處理函數中包含一個對象:event。它的目標爲圖像。即,event.target爲這個圖像節點。
常見的錯誤類型(瞭解錯誤類型以在編寫程序時儘量避免錯誤)
- 數據類型錯誤 :比如,對一個非數組調用了數組方法。
- 類型轉換錯誤:比如,== , != , if, for, while中的條件判斷(布爾值)
- 通信錯誤: 比如,AJAX發送的數據錯誤,服務器響應的數據錯誤
錯誤調試技術
作爲小白的我,以前最喜歡使用的錯誤調試技術莫過於alert(),這樣查看錯誤的方式實在是效率太低。以下爲幾種高效的:
- 瀏覽器中有控制檯,我們可以在控制檯打印相關的信息查找錯誤。
- console.log(message)打印一般性信息
- console.info(message)打印信息性消息
- console.warn(message)打印警告信息
- console.error(message)打印錯誤信息
- 將消息記錄打印到當前頁面的某一具體位置
在頁面中開闢一塊區域,專門用來打印錯誤信息。這個區域可以是一個元素,總是可以出現在頁面中,但僅用於調試目的。
異步任務的錯誤處
使用try-catch來處理錯誤程序時,要注意:哪裏出錯在哪裏try-catch.
function printTime() {
throw new Error("66666");
}
try {
setTimeout(printTime, 1000);
console.log('done');
} catch (e) {
console.log('error');
}
原理:setTimeout爲異步的任務,因此會直接執行打印done的語句,此時沒有報錯,不會執行catch中的代碼。然後到了執行異步任務,瀏覽器接收到錯誤。
這裏的結果是:打印done,瀏覽器的error事件被觸發,因此不會打印error
function printTime() {
try {
throw new Error("66666");
} catch (e) {
console.log('error');
}
}
setTimeout(printTime, 1000);
console.log('done');
這樣就可以用我們自己的catch來處理錯誤了。
記住一點:對會拋出錯誤的代碼寫在try語句塊中,try-catch和throw要在同一層級。
錯誤上傳
- AJAX
- Image對象
建議使用Image對象,主要原因:
- 所有瀏覽器都支持Image對象,包括不支持XMLHttpRequest對象的瀏覽器。
- 可以避免跨域限制。這種情況下使用XMLHttpRequest是不行的。
- 在記錄錯誤的過程中出問題的概率比較低。大多數AJAX通信都是通過Javascript庫提供的包裝函數來處理的,如果庫的代碼本身就有問題,那麼錯誤消息是不會被記錄的。