本文由原作者AshishLahoti授权翻译。在今天的内容中,让我们学习使用try、catch、finally和throw进行错误处理。我们还将讨论JS中的内置错误对象(Error、SyntaxError、ReferenceError等)以及如何定义自定义错误。1、使用try..catch..finally..throw处理JS中的错误,我们主要使用try、catch、finally和throw关键字。try块包含我们需要检查的代码。关键字throw用于抛出自定义错误。catch块处理捕获的错误。finally块是无论最终结果如何都会执行的块。你可以在这个块中做一些需要做的事情。1.1try每个try块必须关联至少一个catch或finally块,否则会抛出SyntaxError错误。我们单独使用try块来验证:try{thrownewError('Errorwhileexecutingthecode');}?UncaughtSyntaxError:Missingcatchorfinallyaftertry1.2try..catch建议try和catch块一起使用,可以优雅地处理try块抛出的错误。try{thrownewError('Errorwhileexecutingthecode');}catch(err){console.error(err.message);}??Errorwhileexecutingthecode1.2.1try..catchwithinvalidcodetry..catchcannotcatch无效的JS代码,比如try块内的以下代码在语法上是错误的,但不会被catch块捕获。try{~!$%^&*}catch(err){console.log("Thiswillnotbeexecuted");}??UncaughtSyntaxError:Invalidorunexpectedtoken1.2.2try..catch和异步代码一样,try..catch不能捕获异步代码中抛出的异常,比如setTimeout:try{setTimeout(function(){noSuchVariable;//undefinedvariable},1000);}catch(err){console.log("Thiswillnotbeexecuted");}UncaughtReferenceError将在1秒后抛出:??UncaughtReferenceError:noSuchVariableisnotdefined因此,我们应该在异步代码中使用try..catch来处理错误:setTimeout(function(){try{noSuchVariable;}catch(err){console.log("erroriscaughtre!");}},1000);1.2.3嵌套的try..catch我们也可以使用嵌套的try和catch块向上抛出错误,如下:);}catch(err){throwerr;}}catch(err){console.log("Errorcaughtbyouterblock:");console.error(err.message);}Errorcaughtbyouterblock:??Errorwhileexecutingthecode1.3try..finallyisnot推荐给你seonlytry..finally没有catch块,看看下面会发生什么:try{thrownewError('Errorwhileexecutingthecode');}finally{console.log('finally');}finallyy??UncaughtError:Errorwhileexecutingthecode这里注意两点:即使try块抛出错误后,finally块也会执行,没有catch块,错误不会被优雅处理,导致未捕获错误1.4try..catch..finally建议使用try...catch块和可选的finally块}catch(err){console.error(err.message);}finally{console.log('Finallyblockalwaysrun');}console.log("代码在try-catch-finally块之外执行继续..");这里还有两点需要注意:try块中抛出错误后,后面的代码将不会执行。即使在try块抛出错误之后,finally块仍然会执行。finally块通常用于清理资源或关闭流,如下所示:try{openFile(file);readFile(file);}catch(err){console.error(err.message);}finally{closeFile(file);}1.5throwthrow语句用于抛出异常。throw//throwprimitivesandfunctionsthrow"Error404";throw42;throwtrue;throw{toString:function(){return"I'manobject!";}};//throwerrorobjectthrownewError('Errorwhileexecutingthecode');thrownewSyntaxError('Somethingiswrongwith')thrownewReferenceError('Oops..Wrongreference');//throwcustomerrorobjectfunctionValidationError(message){this.message=message;this.name='ValidationError';}thrownewValidationError('Valuetoohigh');2、异步代码中的错误处理是针对异步代码的错误处理可以是Promise和asyncawait。2.1then..catchinPromise我们可以使用then()和catch()链接多个Promise来处理链中单个Promise的错误,如下:Promise.resolve(1).then(res=>{console.log(res);//print'1'thrownewError('somethingwentwrong');//throwerrorreturnPromise.resolve(2);//这里不会执行}).then(res=>{//不会执行这里执行是因为错误还没有处理console.log(res);}).catch(err=>{console.error(err.message);//print'somethingwentwrong'returnPromise.resolve(3);}).then(res=>{console.log(res);//print'3'}).catch(err=>{//这个不会执行console.error(err);})我们来看一个更实际的示例,我们使用fetch调用返回promise对象的API,并使用catch块优雅地处理API失败。functionhandleErrors(response){if(!response.ok){throwError(response.statusText);}returnresponse;}fetch("http://httpstat.us/500").then(handleErrors).then(response=>console.log("ok")).catch(error=>console.log("Caught",error));CaughtError:InternalServerErrorrathandleErrors(:3:15)2.2try..catch和asyncawait中的asyncawait是更易于使用try..catch:(asyncfunction(){try{awaitfetch("http://httpstat.us/500");}catch(err){console.error(err.message);}})();让我们看一下同一个例子,我们使用fetch调用返回承诺的API,我们使用try..catch块来优雅地处理API失败。functionhandleErrors(response){if(!response.ok){throwError(response.statusText);}}(asyncfunction(){try{letresponse=awaitfetch("http://httpstat.us/500");handleErrors(response);letdata=awaitresponse.json();returndata;}catch(error){console.log("Caught",error)}})();CaughtError:InternalServerErrorathandleErrors(:3:15)at:11:73。JS3.1中的内置错误ErrorJavaScript有一个内置的错误对象,通常由try块抛出并在catch块中捕获。Error对象包含以下属性:name:错误的名称,例如“Error”、“SyntaxError”、“ReferenceError”等。message:包含错误详细信息的消息。堆栈:是用于调试目的的错误堆栈跟踪。我们创建一个错误对象并查看其名称和消息属性:consterr=newError('Errorwhileexecutingthecode');console.log("name:",err.name);console.log("message:",err.message);console.log("stack:",err.stack);name:Errormessage:Errorwhileexecutingthecodestack:Error:Errorwhileexecutingthecodeat:1:13JavaScript有以下内置错误,由3.2EvalErrorEvalError继承自Error对象关于全局eval()函数中的错误,这个异常不再被JS抛出,它的存在是为了向后兼容。3.3RangeError当值超出范围时,将引发RangeError。?[].length=-1?UncaughtRangeError:Invalidarraylength3.4ReferenceError当引用一个不存在的变量时会引发ReferenceError。?x=x+1;?UncaughtReferenceError:xisnotdefined3.5SyntaxError当您在JS代码中使用任何错误的语法时,将引发SyntaxError。?function(){return'Hi!'}?UncaughtSyntaxError:Functionstatementsrequirefunctionname?1=1?UncaughtSyntaxError:Invalidleft-handsideinaassignment?JSON.parse("{x}");?UncaughtSyntaxError:Unexpectedtokenxin3.JSONatpositionType如果值不是预期类型,一个TypeError被抛出。?1();?UncaughtTypeError:1isnotafunction?null.name;?UncaughtTypeError:Cannotreadproperty'name'ofnull3.7URIError如果以错误的方式使用全局URI方法,则会抛出URIError。?decodeURI("%%%");?UncaughtURIError:URImalformed4。定义并抛出自定义错误我们也可以通过这种方式定义自定义错误。classCustomErrorextendsError{constructor(message){super(message);this.name="CustomError";}};consterr=newCustomError('Customerrorwhileexecutingthecode');console.log("name:",err.name);控制台。log("message:",err.message);name:CustomErrormessage:Customerrorwhileexecutingthecode我们可以进一步增强CustomError对象以包含错误代码classCustomErrorextendsError{constructor(message,code){super(message);this.name="CustomError";这个。code=code;}};consterr=newCustomError('执行代码时出现客户错误',"ERROR_CODE");console.log("name:",err.name);console.log("message:",err.message);安慰。log("code:",err.code);name:CustomErrormessage:Customerrorwhileexecutingthecodecode:ERROR_CODE在try..catch块中使用它:try{try{null.name;}catch(err){thrownewCustomError(err.message,err.name);//message,code}}catch(err){console.log(err.name,err.code,err.message);}CustomErrorTypeErrorCannotreadproperty'name'ofnull本文转载自微信公众号《大千世界》,可通过以下二维码关注和转载本文,请联系大千世界公众号。