編寫JavaScript代碼時,我們要時刻牢記,JavaScript引擎是一個事件驅(qū)動的執(zhí)行引擎秀仲,代碼總是以單線程執(zhí)行,而回調(diào)函數(shù)的執(zhí)行需要等到下一個滿足條件的事件出現(xiàn)后壶笼,才會被執(zhí)行。
例如雁刷,setTimeout()
函數(shù)可以傳入回調(diào)函數(shù)覆劈,并在指定若干毫秒后執(zhí)行:
function printTime() {
console.log('It is time!');
}
setTimeout(printTime, 1000);
console.log('done');
上面的代碼會先打印done
,1秒后才會打印It is time!
沛励。
如果printTime()
函數(shù)內(nèi)部發(fā)生了錯誤责语,我們試圖用try包裹setTimeout()
是無效的:
function printTime() {
throw new Error();
}
tyr {
setTimeout(printTime, 1000);
console.log('done');
} catch (e) {
alert('error');
}
// alert語句不會被執(zhí)行
原因就在于調(diào)用setTimeout()
函數(shù)時,傳入的printTime
函數(shù)并未立刻執(zhí)行目派!緊接著坤候,JavaScript引擎會繼續(xù)執(zhí)行console.log('done');
語句,而此時并沒有錯誤發(fā)生企蹭。直到1秒鐘后白筹,執(zhí)行printTime
函數(shù)時才發(fā)生錯誤,但此時除了在printTime
函數(shù)內(nèi)部捕獲錯誤外谅摄,外層代碼并無法捕獲徒河。
所以,涉及到異步代碼送漠,無法在調(diào)用時捕獲顽照,愿意那就是在捕獲的當(dāng)時,回調(diào)函數(shù)并未執(zhí)行闽寡。
類似的代兵,當(dāng)我們處理一個事件時,在綁定事件的代碼處爷狈,無法捕獲事件處理函數(shù)的錯誤植影。
例如,針對以下的表單:
<form>
<input id="x"> + <input id="y">
<button id="calc" type="button"> 計算 </button>
</form>
我們用下面的代碼給button綁定click事件:
var $btn = $('#calc');
// 取消已綁定的事件:
$btn.off('click');
try {
$btn.click(function () {
var
x = parseFloat($('#x').val()),
y = parseFloat($('#y').val()),
r;
if (isNaN(x) || isNaN(y)) {
throw new Error('輸入有誤');
}
r = x + y;
alert('計算結(jié)果: ' + r);
});
} catch (e) {
alert('輸入有誤淆院!');
}
但是何乎,用戶輸入錯誤時句惯,處理函數(shù)并未捕獲到錯誤。請修復(fù)錯誤處理代碼支救。
所以可以這么寫:
$btn.click(function () {
var
x = parseFloat($('#x').val()),
y = parseFloat($('#y').val()),
r;
try {
if (isNaN(x) || isNaN(y)) {
throw new Error('輸入有誤');
}
}catch (e) {
alert('輸入有誤抢野!');
}
r = x + y;
alert('計算結(jié)果:' + r);
});