JavaScriptµÄʼþÇý¶¯·¶Ê½ÔöÌíÁ˷ḻµÄÓïÑÔ£¬Ò²ÊÇÈÃʹÓÃJavaScript±à³Ì±äµÃ¸ü¼Ó¶àÑù»¯¡£Èç¹û½«ä¯ÀÀÆ÷ÉèÏëΪJavaScriptµÄʼþÇý¶¯¹¤¾ß£¬ÄÇôµ±´íÎó·¢Éúʱ£¬Ä³¸öʼþ¾Í»á±»Å׳ö¡£ÀíÂÛÉÏ¿ÉÒÔÈÏΪÕâЩ·¢ÉúµÄ´íÎóÖ»ÊÇJavaScriptÖеļòµ¥Ê¼þ¡£
±¾ÎĽ«»áÌÖÂÛ¿Í»§¶ËJavaScriptÖеĴíÎó´¦Àí¡£Ö÷Òª½éÉÜJavaScriptÖеÄÒ×·¸´íÎó¡¢´íÎó´¦Àí¡¢Òì²½´úÂë±àдµÈÄÚÈÝ¡£
ÏÂÃæ¾ÍÈÃÎÒÃÇÒ»Æð¿´¿´ÈçºÎÕýÈ·´¦ÀíJavaScriptÖеĴíÎó¡£
DemoÑÝʾ
±¾ÎÄÖÐʹÓõÄdemo¿ÉÒÔÔÚGitHubÉÏÕÒµ½£¬ÔËÐÐÖ®ºó»áÊÇÕâÑùµÄÒ³Ãæ£º

ÿ¸ö°´Å¥¶¼»áÒý·¢Ò»¸ö¡°´íÎó£¨Exception£©¡±£¬Í¬Ê±Õâ¸ö´íÎó»áÄ£Äâ³öÒ»¸ö±»Å׳öµÄÒì³£TypeError¡£ÏÂÃæÊÇÄ£¿éµÄ¶¨Ò壺
// scripts/error.js
function error() {
var foo = {};
return foo.bar();
} |
Ê×ÏÈ£¬Õâ¸öº¯ÊýÉùÃ÷ÁËÒ»¸ö¿Õ¶ÔÏófoo¡£ÐèҪעÒâµÄÊÇ£¬bar( )δÔÚÈκεط½¶¨Òå¡£½ÓÏÂÀ´ÑéÖ¤Õâ¸öµ¥Ôª²âÊÔÊÇ·ñ»áÒý·¢¡°´íÎó¡±£º
// tests/scripts/errorTest.js
it('throws a TypeError', function () {
should.throws(error, TypeError);
}); |
Õâ¸öµ¥Ôª²âÊÔÔÚMochaÖУ¬Í¬Ê±ÔÚ Should.jsÖÐÓвâÊÔÉùÃ÷¡£MochaÊDzâÊÔÔËÐй¤¾ß£¬¶øShould.jsÊǶÏÑÔ¿â¡£Õâ¸öµ¥Ôª²âÊÔÔËÐÐÔÚNodeÉÏ£¬²»ÐèҪʹÓÃä¯ÀÀÆ÷¡£
error( )¶¨ÒåÒ»¸ö¿Õ¶ÔÏó£¬È»ºó³¢ÊÔ·ÃÎÊÒ»¸ö·½·¨¡£ÒòΪbar( )ÔÚ¶ÔÏóÄÚ²»´æÔÚ£¬ËùÒԾͻáÒý·¢Òì³£¡£ÕâÖÖ·¢ÉúÔÚÏñJavaScriptÕâÑùµÄ¶¯Ì¬ÓïÑÔÉϵĴíÎó£¬Ã¿¸öÈË¿ÉÄܶ¼»áÓöµ½£¡
´íÎó´¦Àí£¨Ò»£©
ͨ¹ýÒÔÏ´úÂ룬¶ÔÉÏÊö´íÎó½øÐд¦Àí£º
// scripts/badHandler.js
function badHandler(fn) {
try {
return fn();
} catch (e) { }
return null;
} |
¸Ã´¦Àí³ÌÐò½«fn×÷ΪÊäÈë²ÎÊý£¬È»ºófnÔÚ´¦Àíº¯ÊýÄÚ²¿»á±»µ÷Óᣵ¥Ôª²âÊÔ»áÌåÏÖ³öÒÔÉÏ´íÎó´¦Àí³ÌÐòµÄ×÷Óãº
// tests/scripts/badHandlerTest.js
it('returns a value without errors', function()
{
var fn = function() {
return 1;
};
var result = badHandler(fn);
result.should.equal(1);
});
it('returns a null with errors', function()
{
var fn = function() {
throw new Error('random error');
};
var result = badHandler(fn);
should(result).equal(null);
}); |
Èç¹û³öÏÖÎÊÌ⣬´íÎó´¦Àí³ÌÐò¾Í»á·µ»Ønull¡£fn( )»Øµ÷º¯Êý¿ÉÒÔÖ¸ÏòÒ»¸öºÏ·¨µÄ·½·¨»ò´íÎó¡£
ÒÔϵĵã»÷ʼþ»á¼ÌÐø½øÐÐʼþ´¦Àí£º
// scripts/badHandlerDom.js
(function (handler, bomb) {
var badButton = document.getElementById('bad');
if (badButton) {
badButton.addEventListener('click', function ()
{
handler(bomb);
console.log('Imagine, getting promoted for hiding
mistakes');
});
}
}(badHandler, error)); |
ÕâÖÖ´¦Àí·½Ê½ÔÚ´úÂëÖÐÒþ²ØÁËÒ»¸ö´íÎ󣬲¢ÇÒºÜÄÑ·¢ÏÖ¡£Òþ²ØµÄ´íÎó¿ÉÄܻỨ·ÑºÃ¼¸¸öСʱµÄµ÷ÊÔʱ¼ä¡£ÓÈÆäÊÇÔÚ¾ßÓÐÉî¶Èµ÷ÓöÑÕ»µÄ¶à²ã½â¾ö·½°¸ÖУ¬Õâ¸ö´íÎó»á¸üÄÑ·¢ÏÖ¡£ËùÒÔÕâÊÇÒ»ÖֺܲîµÄ´íÎó´¦Àí·½Ê½¡£
´íÎó´¦Àí£¨¶þ£©
ÏÂÃæÊÇÁíÒ»¸ö´íÎó´¦Àí·½Ê½¡£
// scripts/uglyHandler.js
function uglyHandler(fn) {
try {
return fn();
} catch (e) {
throw new Error('a new error');
}
} |
´¦ÀíÒì³£µÄ·½Ê½ÈçÏÂËùʾ£º
// tests/scripts/uglyHandlerTest.js
it('returns a new error with errors', function
() {
var fn = function () {
throw new TypeError('type error');
};
should.throws(function () {
uglyHandler(fn);
}, Error);
}); |
ÒÔÉ϶ԴíÎóµÄ´¦Àí³ÌÐòÓÐÃ÷ÏԵĸĽø¡£ÔÚÕâÀïÒì³£»áµ÷ÓöÑÕ»½øÐÐðÅÝ¡£Í¬Ê±´íÎó»áÕ¹¿ª¶ÑÕ»£¬Õâ¶Ôµ÷ÊԷdz£ÓаïÖú¡£³ýÁËÅ׳öÒì³££¬½âÊÍÆ÷»¹»áÑØ×ÅջѰÕÒÁíÍâµÄ´¦Àí¡£ÕâÒ²´øÀ´ÁË¿ÉÒÔ´Ó¶ÑÕ»¶¥²¿´¦Àí´íÎóµÄ¿ÉÄÜ¡£µ«Õ⻹ÊÇÒ»ÖֽϲîµÄ´íÎó´¦Àí£¬ÐèÒªÎÒÃÇ´Ó¶ÑÕ»ÖÐÒ»²½²½×·ËÝÔʼµÄÒì³£¡£
¿ÉÒÔ²ÉÓÃÒ»ÖÖÌæ´ú·½°¸£¬ÓÃ×Ô¶¨ÒåµÄ´íÎó·½Ê½À´½áÊøÕâÖֽϲîµÄ´íÎó´¦Àí¡£µ±ÄãÏò´íÎóÖÐÌí¼Ó¸ü¶àÏêϸÐÅϢʱ£¬»áÈÃÕâÖÖ·½·¨±äµÃºÜÓаïÖú¡£
ÀýÈ磺
// scripts/specifiedError.js
// Create a custom error
var SpecifiedError = function SpecifiedError(message)
{
this.name = 'SpecifiedError';
this.message = message || '';
this.stack = (new Error()).stack;
};
SpecifiedError.prototype = new Error();
SpecifiedError.prototype.constructor = SpecifiedError;; |
// scripts/uglyHandlerImproved.js
function uglyHandlerImproved(fn) {
try {
return fn();
} catch (e) {
throw new SpecifiedError(e.message);
}
} |
// tests/scripts/uglyHandlerImprovedTest.js
it('returns a specified error with errors', function
() {
var fn = function () {
throw new TypeError('type error');
};
should.throws(function () {
uglyHandlerImproved(fn);
}, SpecifiedError);
}); |
Ö¸¶¨µÄ´íÎó»áÌí¼Ó¸ü¶àÏêϸÐÅÏ¢²¢±£ÁôÔʼµÄ´íÎóÏûÏ¢¡£ÓÐÁËÕâ¸ö¸Ä½ø£¬ÒÔÉϵĴ¦Àí²»ÔÙÊǽϲîµÄ´¦Àí·½Ê½ÁË£¬¶øÊÇÒ»¸öÇåÎúÓÐÓõķ½Ê½¡£
¾¹ýÁËÉÏÃæµÄ´¦Àí£¬ÎÒÃÇ»¹ÊÕµ½ÁËÒ»¸öδ´¦ÀíµÄÒì³£¡£½ÓÏÂÀ´ÈÃÎÒÃÇ¿´¿´ä¯ÀÀÆ÷ÔÚ´¦Àí´íÎóʱ£¬ÓÐʲô°ïÖú¡£
Õ¹¿ª¶ÑÕ»
´¦ÀíÒì³£µÄÒ»ÖÖ·½Ê½ÊÇÔÚµ÷ÓöÑÕ»µÄ¶¥²¿¼ÓÈëtry...catch¡£
±ÈÈç˵£º
function main(bomb)
{
try {
bomb();
} catch (e) {
// Handle all the error things
}
} |
µ«ÊÇ£¬ä¯ÀÀÆ÷ÊÇʼþÇý¶¯µÄ, JavaScriptÖеÄÒì³£Ò²ÊÇÒ»¸öʼþ¡£·¢ÉúÒ쳣ʱ£¬½âÊÍÆ÷»áÔÝÍ£Ö´Ðв¢Õ¹¿ª£º
// scripts/errorHandlerDom.js
window.addEventListener('error', function (e)
{
var error = e.error;
console.log(error);
}); |
´Ëʼþ´¦Àí³ÌÐò»á²¶»ñÈκÎÖ´ÐÐÉÏÏÂÎÄÖз¢ÉúµÄ´íÎ󡣸÷¸öÄ¿±ê·¢ÉúµÄ´íÎóʼþ»á´¥·¢¸÷ÖÖÀàÐ͵ĴíÎó¡£ÕâÖÖ¼¯ÖÐÔÚ´úÂëÖеĴíÎó´¦ÀíÊǷdz£¼¤½øµÄ¡£Äã¿ÉÒÔʹÓþջ¨Á´´¦Àí·½Ê½À´´¦ÀíÌØ¶¨µÄ´íÎó¡£Èç¹ûÄã×ñÑSOLIDÔÔò£¬¾Í¿ÉÒÔ²ÉÓþßÓе¥Ò»Ä¿µÄ´íÎó´¦Àí·½Ê½¡£ÕâЩ´¦Àí³ÌÐò¿ÉÒÔËæÊ±½øÐÐ×¢²á£¬½âÊÍÆ÷»áÑ»·Ö´ÐÐÐèÒªÖ´ÐеĴ¦Àí³ÌÐò¡£´úÂë¿â¿ÉÒÔ´Ótry...catch¿éÖÐÊͷųöÀ´£¬ÕâҲʹµÃµ÷ÊÔ±äµÃÈÝÒס£ÔÚJavaScriptÖУ¬°Ñ´íÎó´¦Àíµ±×÷ʼþ´¦ÀíºÜÖØÒª¡£
²¶»ñ¶ÑÕ»
ÔÚ½â¾öÎÊÌâʱ£¬µ÷ÓöÑÕ»»á·Ç³£ÓÐÓã¬Í¬Ê±ä¯ÀÀÆ÷ÕýºÃ¿ÉÒÔÌṩÕâЩÐÅÏ¢¡£ËäÈ»¶ÑÕ»ÊôÐÔ²»ÊDZê×¼µÄÒ»²¿·Ö£¬µ«ÊÇ×îеÄä¯ÀÀÆ÷ÒѾ¿ÉÒԲ鿴ÕâЩÐÅÏ¢ÁË¡£
ÏÂÃæÊÇÔÚ·þÎñÆ÷ÉϼǼ´íÎóµÄʾÀý£º
// scripts/errorAjaxHandlerDom.js
window.addEventListener('error', function (e)
{
var stack = e.error.stack;
var message = e.error.toString();
if (stack) {
message += '\n' + stack;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', '/log', true);
// Fire an Ajax request with error details
xhr.send(message);
}); |
ÿ¸ö´íÎó´¦Àí¶¼¾ßÓе¥¸öÄ¿µÄ£¬ÕâÑù¿ÉÒÔ±£³Ö´úÂëµÄDRYÔÔò£¨Ä¿µÄµ¥Ò»£¬²»ÒªÖظ´×Ô¼ºÔÔò£©¡£
ÔÚä¯ÀÀÆ÷ÖУ¬ÐèÒª½«Ê¼þ´¦ÀíÌí¼Óµ½DOM¡£ÕâÒâζ×ÅÈç¹ûÄãÕýÔÚ¹¹½¨µÚÈý·½¿â£¬ÄÇôÄãµÄʼþ»áÓë¿Í»§¶Ë´úÂë¹²´æ¡£window.addEventListener(
)»á°ïÄã½øÐд¦Àí£¬Í¬Ê±Ò²²»»áĨȥÏÖÓеÄʼþ¡£
ÕâÊÇ·þÎñÆ÷ÉÏÈÕÖ¾µÄ½ØÍ¼£º

¿ÉÒÔͨ¹ýÃüÁîÌáʾ·û²é¿´ÈÕÖ¾£¬µ«ÊÇWindowsÉÏ£¬ÈÕÖ¾ÊǷǶ¯Ì¬µÄ¡£
ͨ¹ýÈÕÖ¾¿ÉÒÔÇå³þµÄ¿´µ½£¬¾ßÌåʲôÇé¿ö´¥·¢ÁËʲô´íÎó¡£ÔÚµ÷ÊÔʱµ÷ÓöÑÕ»Ò²»á·Ç³£ÓÐÓã¬ËùÒÔ²»ÒªµÍ¹Àµ÷ÓöÑÕ»µÄ×÷Óá£
ÔÚJavaScriptÖУ¬´íÎóÐÅÏ¢½öÊÊÓÃÓÚµ¥¸öÓò¡£ÒòΪÔÚʹÓÃÀ´×Ô²»ÓÃÓòµÄ½Å±¾Ê±£¬½«»á¿´²»µ½ÈκδíÎóÏêϸÐÅÏ¢¡£
Ò»ÖÖ½â¾ö·½°¸ÊÇÖØÐÂÅ׳ö´íÎó£¬Í¬Ê±±£Áô´íÎóÏûÏ¢£º
try {
return fn();
} catch (e) {
throw new Error(e.message);
} |
Ò»µ©ÖØÐÂÆô¶¯ÁË´íÎ󱸷ݣ¬È«¾Ö´íÎó´¦Àí³ÌÐò¾Í»áÍê³ÉÆäÓàµÄ¹¤×÷¡£È·±£ÄãµÄ´íÎó´¦Àí´¦ÔÚÏàͬÓòÖУ¬ÕâÑù»á±£ÁôÔʼÏûÏ¢£¬¶ÑÕ»ºÍ×Ô¶¨Òå´íÎó¶ÔÏó¡£
Òì²½´¦Àí
JavaScriptÔÚÔËÐÐÒì²½´úÂëʱ£¬½øÐÐÏÂÃæµÄÒì³£´¦Àí£¬»á²úÉúÒ»¸öÎÊÌ⣺
// scripts/asyncHandler.js
function asyncHandler(fn) {
try {
// This rips the potential bomb from the current
context
setTimeout(function () {
fn();
}, 1);
} catch (e) { }
} |
ͨ¹ýµ¥Ôª²âÊÔÀ´²é¿´ÎÊÌ⣺
// tests/scripts/asyncHandlerTest.js
it('does not catch exceptions with errors', function
() {
// The bomb
var fn = function () {
throw new TypeError('type error');
};
// Check that the exception is not caught
should.doesNotThrow(function () {
asyncHandler(fn);
});
}); |
Õâ¸öÒ쳣ûÓб»²¶»ñ£¬ÎÒÃÇͨ¹ýµ¥Ôª²âÊÔÀ´ÑéÖ¤¡£¾¡¹Ü´úÂë°üº¬ÁËtry...catch£¬µ«ÊÇtry...catchÓï¾äÖ»ÄÜÔÚµ¥¸öÖ´ÐÐÉÏÏÂÎÄÖй¤×÷¡£µ±Òì³£±»Å׳öʱ£¬½âÊÍÆ÷ÒѾÍÑÀëÁËtry...catch£¬ËùÒÔÒ쳣δ±»´¦Àí¡£Ajaxµ÷ÓÃÒ²»á·¢ÉúͬÑùµÄÇé¿ö¡£
ËùÒÔ£¬Ò»ÖÖ½â¾ö·½°¸ÊÇÔÚÒì²½»Øµ÷Öв¶»ñÒì³££º
setTimeout(function
() {
try {
fn();
} catch (e) {
// Handle this async error
}
}, 1); |
ÕâÖÖ×ö·¨»á±È½Ï×àЧ£¬µ«ÈÔÓкܴóµÄ¸Ä½ø¿Õ¼ä¡£
Ê×ÏÈ£¬ÕâЩtry...catch blockÔÚÕû¸öÇøÓò¾À²ø²»Çå¡£ÊÂʵÉÏ£¬V8ä¯ÀÀÆ÷ÒýÇæ²»¹ÄÀøÔÚº¯ÊýÄÚʹÓÃtry
... catch block¡£V8ÊÇChromeä¯ÀÀÆ÷ºÍNodeÖÐʹÓõÄJavaScriptÒýÇæ¡£Ò»ÖÖ×ö·¨Êǽ«try...catch
blockÒÆ¶¯µ½µ÷ÓöÑÕ»µÄ¶¥²¿£¬µ«ÕâÈ´²»ÊÊÓÃÓÚÒì²½´úÂë±à³Ì¡£
ÓÉÓÚÈ«¾Ö´íÎó´¦Àí¿ÉÒÔÔÚÈκÎÉÏÏÂÎÄÖÐÖ´ÐУ¬ËùÒÔÈç¹ûΪ´íÎó´¦ÀíÌí¼ÓÒ»¸ö´°¿Ú¶ÔÏó£¬ÄÇô¾ÍÄܱ£Ö¤´úÂëµÄDRYºÍSOLIDÔÔò¡£Í¬Ê±È«¾Ö´íÎó´¦ÀíÒ²Äܱ£Ö¤ÄãµÄÒì²½´úÂëºÜ¸É¾»¡£
ÒÔÏÂÊǸÃÒì³£´¦ÀíÔÚ·þÎñÆ÷Éϵı¨¸æÄÚÈÝ¡£Çë×¢Ò⣬Êä³öÄÚÈÝ»á¸ù¾Ýä¯ÀÀÆ÷µÄ²»Í¬¶ø²»Í¬¡£

´Ó´íÎó´¦ÀíÖпÉÒÔ¿´µ½£¬´íÎóÀ´×ÔÓÚÒì²½´úÂëµÄsetTimeout( )¹¦ÄÜ¡£
½áÂÛ
ÔÚ½øÐдíÎó´¦Àíʱ£¬²»ÒªÒþ²ØÎÊÌ⣬¶øÓ¦¸Ã¼°Ê±·¢ÏÖÎÊÌ⣬²¢²ÉÓø÷ÖÖ·½·¨×·ËÝÎÊÌâµÄ¸ùÔ´ÒÔ±ã½â¾öÎÊÌâ¡£ËäÈ»±àд´úÂëʱ£¬Ê±³£ÄÑÃâ»áÂñÏ´íÎ󣬵«ÊÇÎÒÃÇÒ²ÎÞÐëΪ´íÎóµÄ·¢Éú¹ýÓڸе½ÐßÀ¢£¬¼°Ê±½â¾ö·¢ÏÖÎÊÌâ´Ó¶ø±ÜÃâ¸ü´óµÄÎÊÌâ·¢Éú£¬ÕýÊÇÎÒÃÇÏÖÔÚÐèÒª×öµÄ¡£ |